zkv
Гость
|
|
« : 10-06-2005 10:17 » |
|
Описываю проблему. Пишу сканер локальной сети, т.е. в цикле надо сделать коннект на некоторый порт для компов в диапазоне 192.168.0.1-255. Использую не блокирующие сокеты и функцию select с таймаутом 0.5-1сек. Майкрософт в SP2 для Windows XP ограничила число одновременных коннектов для одного процесса десятью. Под одновременным коннектом понимаются соединения одновременно находящиеся в состоянии SYN_SENT, причем при отсутствии хоста в сети такое состояние длится довольно долго - несколько секунд, что не есть good. Т.е. вызываем функцию connect (не блокирующую), ждем полсекунды в select, если за это время от хоста не пришел ответ, делаем closesocket и переходим к следующему хосту. Вот здесь и начинаются проблемы. Сокет закрыт, но соединение продолжает висеть в состоянии SYN_SENT (проверялось в tcpview). После десяти отсутствующих в сети хостов предел Майкрософт превышается и дальнейшие соединения невозможны. Собственно вопрос: как убивать сокеты зависшие в connect (соединения в состоянии SYN_SENT).
Варианты использовать пропатченный tcpip.sys, увеличить время таймаута и использовать блокирующие сокеты не предлогать.
|
|
|
Записан
|
|
|
|
RXL
Технический
Администратор
Offline
Пол:
|
|
« Ответ #1 : 11-06-2005 09:38 » |
|
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
sss
Специалист
Offline
|
|
« Ответ #2 : 15-06-2005 05:39 » |
|
А зачем ты закрываешь сокет ?
|
|
|
Записан
|
while (8==8)
|
|
|
zkv
Гость
|
|
« Ответ #3 : 16-06-2005 10:27 » |
|
Можно было бы и не закрывать, если бы Мелкософт не ввела ограничение в 10 одновременных коннектов. Что касается приведенной выше ссылки, то все что там сказано относительно closesocket я перепробовал - не помогает. Пожалуй единственное нормальное решени - это создать 10 потоков, использовать блокирующие сокеты и висеть в connect до упора. Правда медленно будет работать
|
|
|
Записан
|
|
|
|
xAndrey
Гость
|
|
« Ответ #4 : 07-05-2010 10:51 » |
|
подниму тему, так как проблема аналогичная, идет конект - дисконект (closesocket()), но происходит просто накопление открытых сокетов.
|
|
|
Записан
|
|
|
|
Finch
Спокойный
Администратор
Offline
Пол:
Пролетал мимо
|
|
« Ответ #5 : 07-05-2010 11:57 » |
|
xAndrey, Ошибка в 10 строке.
|
|
|
Записан
|
Не будите спашяго дракона. Джаффар (Коша)
|
|
|
xAndrey
Гость
|
|
« Ответ #6 : 07-05-2010 14:00 » |
|
ох, понял. в общем тогда так. 1. Есть клиент, который создает несколько потоков, в котором происходит периодические конекты и дисконекты к серверу: ::thFn(...) { myClient* client = new myClient(...); while(1) { if(th->m_stop) { return 1; } client->connect(); // действия какие то .... client->disconnect();
Sleep(sl); } //exit return 1; }
сам socket создаеться s_idx =socket(AF_INET,SOCK_STREAM,0);
дисконект вызывает деструктор в котором сокет устанавливается с параметром нонблокинг. Что происходит: во время запуска потока идет конект, обмен сообщениями клиент сервер, дисконект, при этом Сокет закрыт, но соединение продолжает висеть и с каждой итерацией цикла накапливаеться
|
|
|
Записан
|
|
|
|
Finch
Спокойный
Администратор
Offline
Пол:
Пролетал мимо
|
|
« Ответ #7 : 07-05-2010 14:10 » |
|
netstat что говорит, когда закрыт сокет. По идее говоря данное соединение должно иметь статус CLOSED и висеть некоторое время.
|
|
|
Записан
|
Не будите спашяго дракона. Джаффар (Коша)
|
|
|
RXL
Технический
Администратор
Offline
Пол:
|
|
« Ответ #8 : 07-05-2010 14:12 » |
|
xAndrey,
1. Укажи протокол в третьем параметре socket(). 2. Не видно delete.
Закрывай сокет на disconnect, а не в деструкторе.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
xAndrey
Гость
|
|
« Ответ #9 : 07-05-2010 15:06 » |
|
поправлю себя. xAndrey,
1. Укажи протокол в третьем параметре socket(). 2. Не видно delete.
Закрывай сокет на disconnect, а не в деструкторе.
1.протокол указал IPPROTO_TCP 2. client удаляеться при выходе из потока (пропустио в примере, а отредактировать пост нельзя, или я не нашол как тут это сделать), а дисконект имеет приблизительно такую форму. #ifdef WINDOWS_XP int rez = closesocket(s_idx); #else close(s_idx); #endif
|
|
|
Записан
|
|
|
|
xAndrey
Гость
|
|
« Ответ #10 : 07-05-2010 15:19 » |
|
netstat что говорит, когда закрыт сокет. По идее говоря данное соединение должно иметь статус CLOSED и висеть некоторое время.
показывает состояние ESTABLISHED, хотя закрытия сокета было вызвано и возвратило значение 0.
|
|
|
Записан
|
|
|
|
RXL
Технический
Администратор
Offline
Пол:
|
|
« Ответ #11 : 07-05-2010 21:19 » |
|
Пост редактировать можно, но не новичкам. Защита от странных.
У меня есть толстый талмуд от товарища Стивенса, где рассказывается о поведении сокетов в различных клонах Unix. В общем, они практически одинаково работают. Но в винде все иначе - тут нужно штудировать MSDN в поисках крупиц полезной информации.
Быстрее всего ты не закрываешь сокет, либо в его буфере есть данные на передачу.
Попробуй еще функцию shutdown() перед закрытием.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
xAndrey
Гость
|
|
« Ответ #12 : 08-05-2010 08:27 » |
|
- в MSDN - там только стандартный пример использования. - shutdown() пробовал. - Быстрее всего ты не закрываешь сокет
closesocket() - возвращает 0, что свидетельствует по идее об удачном закрытии.
|
|
|
Записан
|
|
|
|
Finch
Спокойный
Администратор
Offline
Пол:
Пролетал мимо
|
|
« Ответ #13 : 08-05-2010 08:49 » |
|
У меня такая дикая мысль возникла, так как ты открываеш сокеты в отдельных потоках. У тебя индефикатор сокета глобальный или локальный для каждого потока?
|
|
|
Записан
|
Не будите спашяго дракона. Джаффар (Коша)
|
|
|
xAndrey
Гость
|
|
« Ответ #14 : 08-05-2010 09:02 » |
|
локальный. Отдельный класс с мембером :
|
|
|
Записан
|
|
|
|
xAndrey
Гость
|
|
« Ответ #15 : 19-05-2010 16:22 » |
|
В общем проблема решилась вот таким образом: 1) настройкой сокета LINGER lStruct; lStruct.l_onoff = 1; lStruct.l_linger = 0; setsockopt( s_idx, SOL_SOCKET, SO_LINGER,(char *)&lStruct, sizeof(lStruct) );
2)закрытие сокета вот таким образом: CancelIo((HANDLE) s_idx); closesocket( s_idx);
P/S/ может кому то, когда то поможет.
|
|
|
Записан
|
|
|
|
|