| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Сети > socket error: WSAEADDRINUSE(10048) Windows Bug?? |
| Автор: Gradov 5.5.2009, 07:59 |
| Привет. Пытаюсь сделать простого клиента, который подсоединяется к серверу. Клиент должен быть запущен на определенном порту, т.е. вызываю bind. Сервер привязывается к 127.0.0.1:7777 а клиент к 127.0.0.1:7778. Система WinXP SP3. И вот какая странная штука получается: клиент работает без ошибок через раз! Т.е. бывает нормально идут соединения а бывает следующая ошибка: когда я подсоединяюсь к серверу, то первый раз все работает отлично (и bind, и connect), клиент и сервер обмениваются сообщениями. После этого клиент завершается и обязательно вызывается WSACleanup и даже не нужный для Windows Sockets 2 WSACancelBlockingCall(на всякий случай)! И когда я снова пытаюсь подсоединится к серверу вылетает следующая ошибка WSAEADDRINUSE(10048)(Обычно разрешается одно использование адреса сокета). ![]() Причем странно, что это ошибка вылезает после вызова connect, хотя перед этим вызов bind происходит без ошибки!? Даже когда полностью закрываешь приложение клиента все равно вылезает ошибка. Я решил посмотреть какие коннекты есть в системе и выяснилось, что после того как сервер и клиент обменяются информацией и оба закроют сокеты в системе остается соединение с именем процесса [System Process] и остальными данными точно такими же как и у акцептованного сервером сокета (входящее с 127.0.0.01:7778 на 127.0.0.01:7777). ![]() Это соединение через пару минут пропадает и странно, что 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 отключен... |
| Автор: J0ker 5.5.2009, 09:26 |
| это неизбежно 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, 21:11 | ||||
http://msdn.microsoft.com/en-us/library/ms819739.aspx
в некоторых ОС действует, в некоторых нет listening сокет connectionless - ему нечего фактически ждать (кроме ACKов на полуоткрытые сокеты) - поэтому, видими в винде TIME_WAIT для них не выставляется |