Сокет все еще слушает после сбоя приложения - PullRequest
3 голосов
/ 16 декабря 2010

У меня проблема с одним из моих приложений C ++ в Windows 2008x64 (то же самое приложение прекрасно работает в Windows 2003x64).

После сбоя или даже иногда после обычного цикла выключения / перезапуска возникает проблема с использованием сокета на порту 82, необходимого для получения команд.

Глядя на netstat, я вижу, что сокет все еще находится в состоянии прослушивания более 10 минут после остановки приложения (процесс определенно больше не работает).

  TCP    0.0.0.0:82             LISTENING

Я попытался установить сокетвариант REUSEADDR, но, насколько я знаю, это влияет только на повторное подключение к порту, который находится в состоянии TIME_WAIT.В любом случае, это изменение, похоже, не имело никакого значения.

int doReuse = 1;
setsockopt(listenFd, SOL_SOCKET, SO_REUSEADDR,
           (const char *)&doReuse, sizeof(doReuse)); 

Есть идеи, что я могу сделать, чтобы решить или хотя бы избежать этой проблемы?

РЕДАКТИРОВАТЬ:

Сделал netstat -an, но это все, что я получаю:

  TCP    0.0.0.0:82             0.0.0.0:0              LISTENING

Для netstat -anb я получаю:

  TCP    0.0.0.0:82             0.0.0.0:0              LISTENING
 [System]

Я знаю о закрытииизящно, но даже если приложение по какой-то причине вылетает, мне все равно нужно будет его перезапустить.В рассматриваемом приложении используется внутренняя библиотека, которая использует Windows Sockets API.

РЕДАКТИРОВАТЬ:

Очевидно, что для этой проблемы нет решения, поэтому для разработки япойдет с прокси / инструментом, чтобы обойти это.Спасибо за все предложения, высоко ценится.

Ответы [ 6 ]

2 голосов
/ 17 декабря 2010

Если это только причиняет вам вред во время отладки, используйте tcpview от людей sysinternals, чтобы принудительно закрыть сокет.Я предполагаю, что это работает на вашей платформе, но я не уверен.

Если вы выполняете операции блокировки на любых сокетах, не используйте неопределенное время ожидания.По моему опыту, это может вызвать странное поведение на многопроцессорной машине.Я не уверен, что это была ОС Windows Server Server, но это была одна или две версии, предшествовавшие 2003 Server.Вместо неопределенного времени ожидания используйте время ожидания от 30 до 60 секунд, а затем просто повторите ожидание.Это касается и перекрывающихся портов IO и IOCompletion, если вы их используете.

Если это приложение, которое вы отправляете для использования другими, удачи.Windows может быть чистым ублюдком при использовании сокетов ...

1 голос
/ 17 декабря 2010

Я попытался установить опцию сокета в REUSEADDR но насколько я знаю влияет только на переподключение к порту это в состоянии TIME_WAIT.

Это не совсем правильно. Это позволит вам повторно использовать порт в состоянии TIME_WAIT для любых целей, то есть для прослушивания или подключения. Но я согласен, что это не поможет. Я удивлен комментарием о том, что ОС требуется 10 минут, чтобы обнаружить сбойный слушатель. Как только процесс завершится, он должен очистить все ресурсы, кроме портов в состоянии TIME_WAIT.

0 голосов
/ 17 апреля 2015

После просмотра https://superuser.com/a/453827/56937 я обнаружил, что был WerFault процесс, который был приостановлен.

Он, должно быть, унаследовал сокеты от несуществующего процесса, потому что его уничтожение освободило мое прослушиваниепорты.

0 голосов
/ 13 января 2015

http://hea -www.harvard.edu / ~ fine / Tech / addrinuse.html - отличный ресурс для ошибок «Привязка: адрес уже используется».

Некоторые выдержки:

TIME_WAIT - это состояние, которое обычно связывает порт в течение нескольких минут после завершения процесса.Длительность соответствующего таймаута варьируется в разных операционных системах и может быть динамической в ​​некоторых операционных системах, однако типичные значения находятся в диапазоне от одной до четырех минут.

Стратегии предотвращения

SO_REUSEADDR

Это самый простой и эффективный способ уменьшения ошибки «адрес уже используется».

КлиентПервое закрытие

TIME_WAIT можно избежать, если удаленный конец инициирует закрытие.Таким образом, сервер может избежать проблем, разрешив клиенту сначала закрыться.

Сократить время ожидания

Если (по какой-либо причине) ни один из этих вариантов не работает для вас, он также можетможно сократить время ожидания, связанное с TIME_WAIT.

0 голосов
/ 17 декабря 2010

Run

netstat -ano

Это даст вам PID процесса, у которого открыт порт. Проверьте этот процесс в диспетчере задач. Убедитесь, что у вас установлен «список процессов от всех пользователей».

0 голосов
/ 16 декабря 2010

Первое, что нужно проверить, это то, что ваше приложение действительно прослушивает этот порт. Использование:

netstat -anb

чтобы выяснить, какой процесс прослушивает этот порт.

Второе, что нужно проверить, это то, что вы корректно закрываете сокет, когда ваше приложение закрывается. Если вы используете высокоуровневый API сокетов, это не должно быть проблемой (вы используете , используя сокет API, верно?).

Наконец, как структурировано ваше приложение? Это с резьбой? Запускает ли он другие процессы? Откуда вы знаете, что ваше приложение действительно закрыто?

...