2010-12-16 5 views
3

У меня проблема с одним из моих приложений на 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)); 

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

EDIT:

ли 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] 

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

EDIT:

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

+1

Если у вас возникли проблемы даже после перезагрузки компьютера, это может быть какая-то другая программа, использующая ваш порт. Сделайте `netstat -anb`, чтобы увидеть, кто слушает 82. – 2010-12-16 20:44:54

+1

Это нормально после сбоя. Сокет inofrmation хранится в ОС (ваше приложение просто держит дескриптор этой информации). Когда ваше приложение аварийно завершает работу (или завершает работу без закрытия соединения), сокет останется в использовании до тех пор, пока ОС не обнаружит, что приложение для прослушивания ушло (это может быть когда-то хорошее 10 минут). Лучше всего передать в порт аргумент командной строки, чтобы вы могли быстро изменить порт во время де-бинга. – 2010-12-16 21:21:46

+0

У вас есть сообщение об ошибке в журнале событий Windows? Возможно, с кодом 4227 ?. – 2010-12-16 21:42:21

ответ

2

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

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

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

0

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

netstat -anb

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

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

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

0

Run

NetStat -ano

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

1

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

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

0

http://hea-www.harvard.edu/~fine/Tech/addrinuse.html - отличный ресурс для ошибок «Bind: Address Already in Use».

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

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

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

SO_REUSEADDR

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

Клиент закрывает первый

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

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

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

0

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

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

 Смежные вопросы

  • Нет связанных вопросов^_^