Модераторы: feodorv
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> socket error: WSAEADDRINUSE(10048) Windows Bug?? 
:(
    Опции темы
Gradov
Дата 5.5.2009, 07:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 124
Регистрация: 31.10.2006

Репутация: нет
Всего: 3



Привет. Пытаюсь сделать простого клиента, который подсоединяется к серверу. Клиент должен быть запущен на определенном порту, т.е. вызываю bind.
Сервер привязывается к 127.0.0.1:7777 а клиент к 127.0.0.1:7778. Система WinXP SP3.

И вот какая странная штука получается: клиент работает без ошибок через раз! Т.е. бывает нормально идут соединения а бывает следующая ошибка: когда я подсоединяюсь к серверу, то первый раз все работает отлично (и bind, и connect), клиент и сервер обмениваются сообщениями. После этого клиент завершается и обязательно вызывается WSACleanup и даже не нужный для Windows Sockets 2 WSACancelBlockingCall(на всякий случай)! И когда я снова пытаюсь подсоединится к серверу вылетает следующая ошибка WSAEADDRINUSE(10048)(Обычно разрешается одно использование адреса сокета).
user posted image
Причем странно, что это ошибка вылезает после вызова connect, хотя перед этим вызов bind происходит без ошибки!? Даже когда полностью закрываешь приложение клиента все равно вылезает ошибка.

Я решил посмотреть какие коннекты есть в системе и выяснилось, что после того как сервер и клиент обменяются информацией и оба закроют сокеты в системе остается соединение с именем процесса [System Process] и остальными данными точно такими же как и у акцептованного сервером сокета (входящее с 127.0.0.01:7778 на 127.0.0.01:7777).
user posted image
Это соединение через пару минут пропадает и странно, что OutpostFirewall его не видит вообще. Я поначалу думал, что это из-за фаерволла, но отключив его да и антивирус вдобавок, убедился, что ошибка все равно возникает!

Дальше я пробую установить в 1 для клиента с помощью setsockopt параметр SO_REUSEADDR, который разрешает - "Allow the socket to be bound to an address which is already in use". Все равно та же ошибка вылетает!

Далее я пробую разные версии библиотеки Windows Sockets DLL от 1 до 2.2.  Все равно та же ошибка!

Странно также, что сервер запускается и останавливается без проблем без оставления каких-либо соединений с именем [System Process]. Это соединение остается в системе на некоторое время только когда происходит операция accept сервера для клиента, т.е. когда сервер создает параллельное соединение(входящее с 127.0.0.1:7778 на 127.0.0.0.1:7777). Т.е. получается как бы именно этот сокет "превращается" в [System Process] после того как и клиент, и сервер закрывают свои сокеты. Причем даже при закрытии приложения сервера все равно остается в системе на некоторое время(3-4 мин.).

Может кто сталкивался с проблемой? Понимаю, что если клиент и сервер будут на разных компьютерах, то проблеиы в принципе не будет. Также если не использовать bind для клиента, то все вроде бы работает, но эти [System Process] остаются для каждого коннекта клиента акцептованного сервером, просто порты назначаются каждый раз новые и ошибки WSAEADDRINUSE не происходит.

PS: Т.е. получается система как бы блокирует порт, который использовался для соединений на какое-то время! Но Брандмауэр Windows отключен...

Это сообщение отредактировал(а) Gradov - 5.5.2009, 08:04
PM MAIL   Вверх
J0ker
Дата 5.5.2009, 09:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 986
Регистрация: 17.9.2008

Репутация: 1
Всего: 14



это неизбежно
TIME_WAIT - механизм безопасности - после закрытия сокета система некоторое время держит его для того, что-бы все оставшиеся пакеты были выловлены
единственный способ - ждать пока система отпустит сокет - обычно это MSL*2 = 30-120 секунд

ЗЫЖ но SO_REUSEADDR должен в принципе работать если сокет был корректно закрыт... мож вы неправильно выставляете эту опцию? SO_REUSEADDR должен выставляться перед bind

Добавлено через 10 минут и 3 секунды
http://msdn.microsoft.com/en-us/library/ms740621(vs.85).aspx

Это сообщение отредактировал(а) J0ker - 5.5.2009, 09:30


--------------------
user posted image
PM MAIL   Вверх
Gradov
Дата 5.5.2009, 18:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 124
Регистрация: 31.10.2006

Репутация: нет
Всего: 3



Цитата(J0ker @  5.5.2009,  09:26 Найти цитируемый пост)
ЗЫЖ но SO_REUSEADDR должен в принципе работать если сокет был корректно закрыт... мож вы неправильно выставляете эту опцию? SO_REUSEADDR должен выставляться перед bind

Код

int sopt,sopt_size;
...
//проверяю текущее значение SO_REUSEADDR-------------------------------
 sopt_size=sizeof(int);
 if (getsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&sopt,&sopt_size)!=0)
 {
  ErrorSocketMessage("Ошибка getsockopt");
  return;
 }
 //после этого sopt=0
//----------------------------------------------------------------------

//устанавливаю значение SO_REUSEADDR в 1-------------------------------
 sopt=1;
 if (setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&sopt,sizeof(int))!=0)
 {
  ErrorSocketMessage("Ошибка setsockopt");
  return;
 }
//----------------------------------------------------------------------

//проверяю текущее значение SO_REUSEADDR-------------------------------
 sopt_size=sizeof(int);
 if (getsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&sopt,&sopt_size)!=0)
 {
  ErrorSocketMessage("Ошибка getsockopt");
  return;
 }
 //после этого sopt=1
//----------------------------------------------------------------------


Цитата(J0ker @  5.5.2009,  09:26 Найти цитируемый пост)

TIME_WAIT - механизм безопасности - после закрытия сокета система некоторое время держит его для того, что-бы все оставшиеся пакеты были выловлены
единственный способ - ждать пока система отпустит сокет - обычно это MSL*2 = 30-120 секунд

А можно это значение как то изменить? В реестре или где-то в настройках системы?
Еще странно то, что, например, сервер может закрывать свой сокет а потом открывать и привязываться к тому же порту без проблем! При этом не создается ни одного соединения с именем процесса [System Process]. То есть как бы для сервера не действует эта политика безопасности. Почему?



Это сообщение отредактировал(а) Gradov - 5.5.2009, 18:30
PM MAIL   Вверх
J0ker
Дата 5.5.2009, 21:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 986
Регистрация: 17.9.2008

Репутация: 1
Всего: 14



Цитата(Gradov @  5.5.2009,  18:19 Найти цитируемый пост)
А можно это значение как то изменить? В реестре или где-то в настройках системы?

http://msdn.microsoft.com/en-us/library/ms819739.aspx

Цитата(Gradov @  5.5.2009,  18:19 Найти цитируемый пост)
Еще странно то, что, например, сервер может закрывать свой сокет а потом открывать и привязываться к тому же порту без проблем! При этом не создается ни одного соединения с именем процесса [System Process]. То есть как бы для сервера не действует эта политика безопасности. Почему?

в некоторых ОС действует, в некоторых нет
listening сокет connectionless - ему нечего фактически ждать (кроме ACKов на полуоткрытые сокеты) - поэтому, видими в винде TIME_WAIT для них не выставляется


--------------------
user posted image
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Сети | Следующая тема »


 




[ Время генерации скрипта: 0.0701 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.