2013-04-09 3 views
56

Я написал небольшую программу, которая взаимодействует с сервером на определенном порту. Программа работает нормально, но:Как удалить соединение сокета CLOSE_WAIT

После того, как программа была неожиданно завершена, и с тех пор, как это соединение сокета отображается в CLOSE_WAIT. Если я пытаюсь запустить программу, она зависает, и мне нужно ее закрыть, которая накапливает даже .CLOSE_WAIT разъемы.

Есть ли способ сбросить эти соединения?

+2

Вы не можете (и не должны). CLOSE_WAIT - это состояние, определяемое TCP для закрытых соединений, ожидающих подтверждения этого партнера. – vonbrand

+0

См. Также http://unix.stackexchange.com/questions/10106/orphaned-connections-in-close-wait-state ... который я не буду голосовать как дубликат, потому что это закончит закрытие вопроса как вне темы. – derobert

+3

@vonbrand Нет, это не так, это как раз наоборот. Это состояние для соединения, которое уже было закрыто одноранговым узлом и ждет, когда локальное приложение закроет его конец. – EJP

ответ

49

CLOSE_WAIT означает, что ваша программа все еще работает и не закрыла сокет (и ядро ​​ждет его, чтобы это сделать). Добавьте -p в netstat, чтобы получить pid, а затем убейте его сильнее (при необходимости SIGKILL). Это должно избавиться от ваших сокетов CLOSE_WAIT. Вы также можете использовать ps, чтобы найти pid.

SO_REUSEADDR для серверов и TIME_WAIT разъемов, поэтому здесь не применяется.

+1

ну ... kiling процесс может быть не лучшим, если эта программа открывает много соединений, только некоторые из тех, кто находится в «CLOSE_WAIT»: в этом случае убийство процесса может быть совершенно невозможно или неуместно (программа все еще работает и предоставляет услуги, с этими другими соединениями). Просто закрыть ожидающее соединение было бы гораздо более подходящим. но на самом деле это сама программа, которая не закрывает локально connectino (CLOSE_WAIT означает, что он получил «FIN» с другого конца, и программе просто нужно закрыть соединение локально). Отчет об ошибке может быть уместным –

5

У меня также такая же проблема с очень последним сервером Tomcat (7.0.40). Он не реагирует один раз на пару дней.

Чтобы увидеть открытые соединения, вы можете использовать:

sudo netstat -tonp | grep jsvc | grep --regexp="127.0.0.1:443" --regexp="127.0.0.1:80" | grep CLOSE_WAIT 

Как уже упоминалось в this post, вы можете использовать /proc/sys/net/ipv4/tcp_keepalive_time для просмотра значений. Значение, по-видимому, находится в секундах и по умолчанию равно 7200 (т. Е. 2 ​​часа).

Чтобы изменить их, вам необходимо отредактировать /etc/sysctl.conf.

Open/create `/etc/sysctl.conf` 
Add `net.ipv4.tcp_keepalive_time = 120` and save the file 
Invoke `sysctl -p /etc/sysctl.conf` 
Verify using `cat /proc/sys/net/ipv4/tcp_keepalive_time` 
+3

ответ путают. вы сказали, что не реагирующие состояния ушли на несколько дней .. но затем вы также попытаетесь установить время сохранения в течение только 120 секунд. даже со значением по умолчанию (7200 секунд), оно не должно длиться несколько дней, верно? – fanchyna

27

Как описано Crist Clark.

CLOSE_WAIT означает, что локальный конец связи получил FIN с другого конца, но операционная система ожидает программы на локальном конце на самом деле закрыть соединение.

Проблема заключается в том, что ваша программа работает на локальной машине не , закрывая сокет. Это не проблема настройки TCP. Соединение может (и вполне корректно) оставаться на CLOSE_WAIT навсегда, пока программа держит соединение открытым.

После того, как локальная программа закрывает сокет, ОС может отправить FIN на удаленный конец, который переводит вас на LAST_ACK, пока вы ждете ACK FIN. Как только это будет получено, соединение будет завершено и выпадет из таблицы соединений (если ваш конец находится в CLOSE_WAIT, вы do не в конечном итоге в состоянии TIME_WAIT).

+2

как закрыть розетку ?? –

+0

Вы закрываете ручку, которую у вас есть, к открытому гнезду. Используйте 'close()' или 'closesocket()', в зависимости от используемой вами платформы. –

4

Несмотря на то, что слишком много соединений CLOSE_WAIT означает, что в вашем коде что-то не так, и это принято неправильно.

Вы можете проверить: https://github.com/rghose/kill-close-wait-connections

Что делает этот сценарий посылает вне АСК, который соединение было ждет.

Это то, что сработало для меня.

+0

вы отправляете действие для близкого ожидания сокета. с не работает .. если работает, почему? – Chinaxing

+0

Я предполагаю, что ОС уже отправила FIN на удаленный хост. Возможно, удаленный хост не может ответить ACK, который ожидает сокет. – mirage

+0

Да, это правильно (из кода ядра). но я также сомневаюсь в SEQ пакета, который вы отправляете, а это «10», не проверяет ядро? – Chinaxing

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