Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: connect, closesocket и SYN_SENT  (Прочитано 25697 раз)
0 Пользователей и 11 Гостей смотрят эту тему.
zkv
Гость
« : 10-06-2005 10:17 » new

Описываю проблему. Пишу сканер локальной сети, т.е. в цикле надо сделать коннект на некоторый порт для компов в диапазоне 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
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #1 : 11-06-2005 09:38 » 

Почитай тут: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/closesocket_2.asp
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
sss
Специалист

ru
Offline 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
Спокойный
Администратор

il
Offline 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);

дисконект вызывает деструктор в котором
Код:
closesocket(s_idx);


Код:
closesocket(s_idx);

сокет устанавливается с параметром нонблокинг.
Что происходит: во время запуска потока идет конект, обмен сообщениями клиент сервер, дисконект, при этом Сокет закрыт, но соединение продолжает висеть и с каждой итерацией цикла накапливаеться
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #7 : 07-05-2010 14:10 » 

netstat что говорит, когда закрыт сокет. По идее говоря данное соединение должно иметь статус CLOSED и висеть некоторое время.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #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
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #11 : 07-05-2010 21:19 » 

Пост редактировать можно, но не новичкам. Защита от странных.

У меня есть толстый талмуд от товарища Стивенса, где рассказывается о поведении сокетов в различных клонах Unix. В общем, они практически одинаково работают. Но в винде все иначе - тут нужно штудировать MSDN в поисках крупиц полезной информации.

Быстрее всего ты не закрываешь сокет, либо в его буфере есть данные на передачу.

Попробуй еще функцию shutdown() перед закрытием.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
xAndrey
Гость
« Ответ #12 : 08-05-2010 08:27 » 

- в MSDN - там только стандартный пример использования.
- shutdown() пробовал.
-
Быстрее всего ты не закрываешь сокет
closesocket() - возвращает 0, что свидетельствует по идее об удачном закрытии.
 
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #13 : 08-05-2010 08:49 » 

У меня такая дикая мысль возникла, так как ты открываеш сокеты в отдельных потоках. У тебя индефикатор сокета глобальный или локальный для каждого потока?
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
xAndrey
Гость
« Ответ #14 : 08-05-2010 09:02 » 

локальный. Отдельный класс с мембером :
Код:
private:
     SOCKET s_idx;
Записан
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/ может кому то, когда то поможет.
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines