Re: Socket.Close
От: Andir Россия
Дата: 26.06.08 08:42
Оценка: 2 (1)
Здравствуйте, -Cheese-, Вы писали:

C>Почему может возникать такая проблема или это нормальное поведение?


Взять Process Explorer от Sysinternals и посмотреть что за хендлы открыты и сделать выводы.

С Уважением, Andir!
using( RSDN@Home 1.2.0 alpha 4 rev. 987 ) { /* Работаем */ }
Re: Socket.Close
От: matumba  
Дата: 26.06.08 09:34
Оценка: 1 (1)
Здравствуйте, -Cheese-, Вы писали:

C>Имеется самописный сервер на Socket-ах работающий в режиме

C>ацептим клиента — получаем запрос — отвечаем — дисконектим
C>Если смотреть через таскменеджер, то видно что для этого приложения постоянно увеличивается количество Handles.

Я не знаю, про какие handles речь, но возможно это аналогичный случай: наш сервер работает под неприлично малой нагрузкой 80 клиентов/сек. При увеличении числа клиентов, сервер не падает, но соединения больше не принимает — выдаёт отлуп. Выяснилось, что это особенность TCP/IP стека (любого, я так понимаю): после закрытия сокета (неважно кем), драйвер его не освобождает, но ставит в состояние time_wait на примерно 3 минуты (так в стандарте сказано). Это делается для того, чтобы если в сети гуляют ещё не дошедшие пакеты (предназначенные для данного сокета), их можно было распознать и выбросить. Что за му%#$к это выдумал — не знаю, но факт тот, что выше 80 мы подняться не можем. Да и эти 80 со временем падают.
По идее, раз сокет спит в time_wait, должны юзаться остальные 65 тыщ сокетов, но это не происходит. Так что и не знаю на что грешить — на винду, дотнет, TCP, луну и чего ещё.

Посмотрите ещё этот класс — я его не пробовал, но по тестам он в 3 раза круче. Удачи!
Socket.Close
От: -Cheese-  
Дата: 25.06.08 11:59
Оценка:
Всем привет.

Имеется самописный сервер на Socket-ах работающий в режиме
ацептим клиента — получаем запрос — отвечаем — дисконектим
Нагрузка достаточно приличная (в пик работы около 10-20 запросов в секунду).

Если смотреть через таскменеджер, то видно что для этого приложения постоянно увеличивается количество Handles.
За пару дней работы — около 10000 и эта цифра вечно растёт. Утечка какая-то что ли.....

Начал разбираться с причиной... думал где-то не закрываю сокеты (хотя столько активных сокетов в винде и не создашь).
После проверки выяснилось, что всё ок., всё во всех случаях закрывается.
Даже поставил счётчик при открывании и при закрывании и наблюдал за значениями — всё ок (т.е количество Socket.Close равно количеству заасептченых клиентов).
Для каждого коннекта создаются пару калассов, но они все после дисконнекта диспозятся.

Почему может возникать такая проблема или это нормальное поведение?
... << RSDN@Home 1.2.0 alpha 3 rev. 938>>
Re: Socket.Close
От: HowardLovekraft  
Дата: 25.06.08 12:05
Оценка:
Здравствуйте, -Cheese-, Вы писали:
C>Почему может возникать такая проблема или это нормальное поведение?
А TCP View не пробовали запускать? Что показывает?
Re[2]: Socket.Close
От: -Cheese-  
Дата: 25.06.08 12:37
Оценка:
Здравствуйте, HowardLovekraft, Вы писали:

HL>А TCP View не пробовали запускать? Что показывает?

ну есть куча коннектов... в принципе показывает реальное их количество
а что же такое handles?
... << RSDN@Home 1.2.0 alpha 3 rev. 938>>
Re: Socket.Close
От: Аноним  
Дата: 25.06.08 13:03
Оценка:
а зачем каждый раз закрывать сокет? это ведь тоже достаточно ресурсоемкая задача, которая может потребовать времени (закрытие соединения должно быть корректно обработано с двух концов — сервера и клиента). если запросы на сервер идут достаточно часто, и он каждый раз после запроса закрывает соединение, то можно наблюдать не очень хорошую картину. как точно выразить в техническом жаргоне я уже не помню (книжку по TCP/IP читал достаточно давно), но если на пальцах, то следующее: в сетевом буфере накапливаются необработанные пакеты, отвечающие за закрытие сокета. это происходит потому что, запрос на новое соединение приходит слижком часто, и клиент может это соединение потребовать раньше, чем было корректно закрыто предыдущее. для закрытия соединения сервер отправляет на клиент служебные пакеты, на которые клиент отвечает, и после этого оба закрывают сокет. ответ от клиента еще может не успеть придти, как сервер вынужден открывать новое соедиенени. в результате, в сетевом буфере происходит накопление необработанных пакетов, конечным итогом будет переполнение этого буфера. и, как следствие, сильные тормоза в сети, которые не исчезнут по истечение какого то таймаута.

я бы порекомендовал подумать в сторону "не закрывать сокет сразу". то есть сделать умный сервер. получаем от клиента запрос, ассептим его, отвечаем на его команды. потом запускаем таймаут, по истечение которого соединение закрываем. ну или совсем просто вариант — в сетевой протокол добавить новую команду, которой клиент будет говорить серверу о том, что сокет нужно закрыть. смысл — не открывать / закрывать сетевое соединени слижком часто, так как эта операция достаточно ресурсоемкая и требует времени.
Re[3]: Socket.Close
От: HowardLovekraft  
Дата: 25.06.08 13:46
Оценка:
в handles, НЯП, task manager учитывает много чего, те же открытые файлы...
состояние сокетов — established, close_wait, time_wait?
Re[4]: Socket.Close
От: -Cheese-  
Дата: 25.06.08 14:17
Оценка:
Здравствуйте, HowardLovekraft, Вы писали:

HL>в handles, НЯП, task manager учитывает много чего, те же открытые файлы...

HL>состояние сокетов — established, close_wait, time_wait?
файлов никаких не открываю
у сокетов TIME_WAIT
Количество сокетов в списке netstat не связано с количеством хендлов в таскменеджере, хендлов значительно больше
... << RSDN@Home 1.2.0 alpha 3 rev. 938>>
Re[2]: Socket.Close
От: -Cheese-  
Дата: 25.06.08 14:17
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>а зачем каждый раз закрывать сокет? это ведь тоже достаточно ресурсоемкая задача, которая может потребовать времени (закрытие соединения должно быть корректно обработано с двух концов — сервера и клиента).


При запросе клиент создаёт новый коннект и в течении коннекта будет только один запрос и один ответ.

А>если запросы на сервер идут достаточно часто, и он каждый раз после запроса закрывает соединение, то можно наблюдать не очень хорошую картину. как точно выразить в техническом жаргоне я уже не помню (книжку по TCP/IP читал достаточно давно), но если на пальцах, то следующее: в сетевом буфере накапливаются необработанные пакеты, отвечающие за закрытие сокета. это происходит потому что, запрос на новое соединение приходит слижком часто, и клиент может это соединение потребовать раньше, чем было корректно закрыто предыдущее. для закрытия соединения сервер отправляет на клиент служебные пакеты, на которые клиент отвечает, и после этого оба закрывают сокет. ответ от клиента еще может не успеть придти, как сервер вынужден открывать новое соедиенени. в результате, в сетевом буфере происходит накопление необработанных пакетов, конечным итогом будет переполнение этого буфера. и, как следствие, сильные тормоза в сети, которые не исчезнут по истечение какого то таймаута.


А>я бы порекомендовал подумать в сторону "не закрывать сокет сразу". то есть сделать умный сервер. получаем от клиента запрос, ассептим его, отвечаем на его команды. потом запускаем таймаут, по истечение которого соединение закрываем. ну или совсем просто вариант — в сетевой протокол добавить новую команду, которой клиент будет говорить серверу о том, что сокет нужно закрыть. смысл — не открывать / закрывать сетевое соединени слижком часто, так как эта операция достаточно ресурсоемкая и требует времени.


Клиентов (различных IP) очень много. В данном случае лучше сразу закрыть и не морочить голову.
... << RSDN@Home 1.2.0 alpha 3 rev. 938>>
Re[5]: Socket.Close
От: HowardLovekraft  
Дата: 25.06.08 14:32
Оценка:
C>у сокетов TIME_WAIT
А какое значение TcpTimedWaitDelay в настройках TCP/IP?
C>Количество сокетов в списке netstat не связано с количеством хендлов в таскменеджере, хендлов значительно больше
Так может утечка не связана с сокетами? Файлы, ивенты, мьютексы?
Re[6]: Socket.Close
От: -Cheese-  
Дата: 25.06.08 14:45
Оценка:
Здравствуйте, HowardLovekraft, Вы писали:

HL>Так может утечка не связана с сокетами? Файлы, ивенты, мьютексы?

Этого ничего нет....
А что ещё может быть в списке хендлов?
... << RSDN@Home 1.2.0 alpha 4 rev. 1092>>
Re[3]: Socket.Close
От: Аноним  
Дата: 25.06.08 14:56
Оценка:
создание надежного, быстрого и отказойстойчивого сервера — это как раз таки такая задача, над которой стоит поморочить голову
Re: Socket.Close
От: AlexSorokoletov Беларусь http://sorokoletov.com
Дата: 26.06.08 08:12
Оценка:
Здравствуйте, -Cheese-, Вы писали:

C>Всем привет.


C>Имеется самописный сервер на Socket-ах работающий в режиме

C>ацептим клиента — получаем запрос — отвечаем — дисконектим
C>Нагрузка достаточно приличная (в пик работы около 10-20 запросов в секунду).

C>Если смотреть через таскменеджер, то видно что для этого приложения постоянно увеличивается количество Handles.

C>За пару дней работы — около 10000 и эта цифра вечно растёт. Утечка какая-то что ли.....

C>Начал разбираться с причиной... думал где-то не закрываю сокеты (хотя столько активных сокетов в винде и не создашь).

C>После проверки выяснилось, что всё ок., всё во всех случаях закрывается.
C>Даже поставил счётчик при открывании и при закрывании и наблюдал за значениями — всё ок (т.е количество Socket.Close равно количеству заасептченых клиентов).
C>Для каждого коннекта создаются пару калассов, но они все после дисконнекта диспозятся.

C>Почему может возникать такая проблема или это нормальное поведение?

Советую обратить внимание на правильную обработку исключений и вообще паттерны правильной работы с сокетами.
У нас была утечка памяти из-за того, что мы неправильно работали с WCF-сервисами.
Хотя использовали мы их в using(Client c = new Client()){...}, оказывается, сие для WCF не есть правильно.
Re[2]: Socket.Close
От: -Cheese-  
Дата: 26.06.08 10:36
Оценка:
Здравствуйте, Andir, Вы писали:

A>Взять Process Explorer от Sysinternals и посмотреть что за хендлы открыты и сделать выводы.


Висит кучища хендлов
File \Device\Afd\Endpoint

Погуглил по \Device\Afd\Endpoint, но ничего конкретного не нашёл...
... << RSDN@Home 1.2.0 alpha 4 rev. 1092>>
Re[2]: Socket.Close
От: HowardLovekraft  
Дата: 26.06.08 11:48
Оценка:
Здравствуйте, matumba, Вы писали:
M>после закрытия сокета (неважно кем), драйвер его не освобождает, но ставит в состояние time_wait на примерно 3 минуты M>(так в стандарте сказано)
В стадарте чего?
Вот здесь
Автор: HowardLovekraft
Дата: 25.06.08
я не зря спросил про значение параметра TcpTimedWaitDelay, отвечающего за время пребывания в time_wait. В венике он находится в диапазоне от 30 до 300 секунд. Дефолтное значение — 240 секунд.

Если имеет место частый коннект/дисконнект — его нужно уменьшать.
Еще любопытно узнать значение MaxUserPort у автора темы.
Re[3]: Socket.Close
От: HowardLovekraft  
Дата: 26.06.08 11:51
Оценка:
Здравствуйте, -Cheese-, Вы писали:
C>Висит кучища хендлов
C>File \Device\Afd\Endpoint
НЯП, хэндл "\Device\Afd\Endpoint" появляется после успешного вызова socket().
Re[3]: Socket.Close
От: matumba  
Дата: 26.06.08 12:14
Оценка:
Здравствуйте, HowardLovekraft, Вы писали:

HL>Здравствуйте, matumba, Вы писали:

M>>после закрытия сокета (неважно кем), драйвер его не освобождает, но ставит в состояние time_wait на примерно 3 минуты M>(так в стандарте сказано)
HL>В стадарте чего?

Мне отвечать на этот смешной вопрос или вы знаете что-то помимо RFC?

HL>Вот здесь
Автор: HowardLovekraft
Дата: 25.06.08
я не зря спросил про значение параметра TcpTimedWaitDelay, отвечающего за время пребывания в time_wait. В венике он находится в диапазоне от 30 до 300 секунд. Дефолтное значение — 240 секунд.


Это замечательно, что вы обладаете сим глубоким познанием. Но нельзя ли говорить более конкретно, параметр ЧЕГО закодирован в этом загадочном наборе букв? Это что, конфиг дотнета, поле класса, ключ регистри?


HL>Если имеет место частый коннект/дисконнект — его нужно уменьшать.


По идее — да. Но ведь и 4 минуты не с потолка взяли? Не повлияет ли уменьшение таймаута на безошибочность работы?
Re[4]: Socket.Close
От: HowardLovekraft  
Дата: 26.06.08 12:27
Оценка:
Здравствуйте, matumba, Вы писали:

M>Здравствуйте, HowardLovekraft, Вы писали:


HL>>Здравствуйте, matumba, Вы писали:

M>>>после закрытия сокета (неважно кем), драйвер его не освобождает, но ставит в состояние time_wait на примерно 3 минуты M>(так в стандарте сказано)
HL>>В стадарте чего?

M>Мне отвечать на этот смешной вопрос или вы знаете что-то помимо RFC?

Гы. ГОСТ.
Правда, не уверен, что там есть что-то о TCP.

M>нельзя ли говорить более конкретно, параметр ЧЕГО закодирован в этом загадочном наборе букв?

Параметр драйвера TCP в реестре, см. HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters.
MaxUserPort там же.
Думаю, гугл ответил бы на этот вопрос. К чему сарказм?

M>По идее — да. Но ведь и 4 минуты не с потолка взяли? Не повлияет ли уменьшение таймаута на безошибочность работы?

С чего бы? В моем случае при 4-х минутах очень быстро случалось WSAENOBUFS.
Re[5]: Socket.Close
От: HowardLovekraft  
Дата: 26.06.08 12:54
Оценка:
В дополнение:
TCP/IP and NBT configuration parameters for Windows XP.

Note In Microsoft Windows 2000, the default value is 240 seconds. For Windows XP and Microsoft Windows Server 2003, the default was changed to 120 seconds for the IPv4 stack to increase performance. The default value for the IPv6 stack is 240 seconds.


и еще любопытная статья: The TIME-WAIT state in TCP and Its Effect on Busy Servers.
Re[4]: Socket.Close
От: -Cheese-  
Дата: 01.07.08 11:56
Оценка:
Здравствуйте, HowardLovekraft, Вы писали:

HL>НЯП, хэндл "\Device\Afd\Endpoint" появляется после успешного вызова socket().


И как его прибить, когда он уже не нужен?
... << RSDN@Home 1.2.0 alpha 4 rev. 1092>>
Re[4]: Socket.Close
От: -Cheese-  
Дата: 02.07.08 07:13
Оценка:
Здравствуйте, HowardLovekraft, Вы писали:

HL>НЯП, хэндл "\Device\Afd\Endpoint" появляется после успешного вызова socket().

С запуска старттопика количество хендлов уже достигло 22000....
... << RSDN@Home 1.2.0 alpha 4 rev. 1092>>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.