LINUX.ORG.RU

CLOSE_WAIT ?


0

0

Написал сервак ... все класно, но когда начал его юзать на "выносливость", то выяснилось, что при коннекте к нему nc xxx.xxx.xxx.xxx port и последующим ctrl-c на серевере вешается CLASE_WAIT на годы долгие )) в чем дело и как с ним бороться, также можно DoS поймать (((, сервак нитевый, с процессами все ясно, убил и конци в воду )))

anonymous

Не понял, кого убиваем по ctrl-c? Если сервер, то не должно быть так, net/ipv4/tcp.c:tcp_close() переведет в TCP_LAST_ACK если были в TCP_CLOSE_WAIT. Если убит клиент, то это нормально, и ошибка в сервере. Он должен закрыть socket. Полезно посмотреть на сессию tcpdump'ом, посылает ли сервер FIN+ACK?

idle ★★★★★
()

Это не на сервере. Это фишка tcp\ip. Он будет ожидать еще некоторое время пакеты, которые могли еще не дойти серверу посли того как ты его отключил. Это сделано для устойчивости клиентов, и чтоб rst лишний раз не слать, прочитай RFC или книжку по TCP_IP. И еще ты уверен что там не TIME_WAIT?

OxiD ★★★★
()

Вот как раз TIME_WAIT для того, чтобы ждать некоторое время и

повторять ACK на последний FIN, так как этот ACK может потеряться,

и другой конец будет FIN повторять.



CLOSE_WAIT наступает, когда приходит первый FIN от инициатора

shutdown. Теперь ПРОЦЕСС должен закрыть socket - пока он это

не сделает, состояние не изменится.



В обоих случаях при получении пакета с новыми данными будет

выслан RST.

idle ★★★★★
()

Короче,
    {
        int val = 1;
        setsockopt(socket,SOL_SOCKET,SO_REUSEADDR,&val,sizeof(val));
    }
сразу после создания сокета через socket() решит эту проблему (для
того оно и придумано).

hvv
()

Нет, SO_REUSEADDR совсем не для того придумано. Это для борьбы с EADDRINUSE в случае, если делается bind() на локальный порт, а на этом порту уже есть connected socket. Например, в состоянии TIME_WAIT. После bind() флаг никак не меняет поведение socket'а.

idle ★★★★★
()

Да, я прогнал - думал мы сервер убиваем, а не nc. Тогда на сервере просто сокет надо закрыть (read вернет -1 или 0 - легко это задетектить).
PS: idle а для чего тогда /proc/sys/net/ipv4/vs/timeout_closewait - что будет делаться по истечение того времени?

hvv
()

А что, есть такой файл /proc/sys/net/ipv4/vs/timeout_closewait ? Я даже не нашел, кто бы мог этот каталог зарегистерить. Очень интересно, это какое ядро ядро? Насчет детектирования тоже не так просто, возможна туча сценариев, когда read() вернет не ноль. Например. Хост А пишет в socket "bye" и закрывает его. Хост В что-то пишет в socket, write() возвращает успех. Пакет от В доходит до А, тот высылает RST, В его получает, выставляет sock->err = EPIPE. Теперь на В: 1 read() == -EPIPE (sock->err и очищает его), 2 read() == "bye", 3 read() == 0.

idle ★★★★★
()

Пардон пардон, не заметил, что hvv написал "-1 или 0".

idle ★★★★★
()

Братва, сокеты пишу не в первый раз, и отличить TIME_WAIT от TIME_CLOSE тоже могу, все что нужно оп сети уходит и приходит, гарантировано выполнаяется close(socket_descriptor) без ошибок, RFC почти наизусть знаю, и на вопрос как далеко находится клиент -- в соседней дырке в свиче 100М, короче все сигналы я ему послал блокировал и разблокировал PIPE и т.д. Я уже сразу закрывал сокет после accept - боюсь это глюк - или что-то в ядре, хотя на другой тачке с такойже конфигурацией летает без воросов

anonymous
()

idle: /proc/sys/net/ipv4/vs/timeout_closewait - есть в linux-2.2

hvv
()

hvv: ну нет такого файла (и каталога) в 2.20, я даже grep'ом искал в исходниках. Может, патчи какие стоят? А что еще в этом каталоге у тебя?

idle ★★★★★
()

Да, патчи стоят - кажется все из ядра altlinux spring 2001. Ядро 2.2.17.
Список файлов:
[hvv@h hvv]$ ls /proc/sys/net/ipv4/vs/
am_droprate  secure_tcp           timeout_icmp     timeout_synsent
amemthresh   timeout_close        timeout_lastack  timeout_timewait
debug_level  timeout_closewait    timeout_listen   timeout_udp
drop_entry   timeout_established  timeout_synack
drop_packet  timeout_finwait      timeout_synrecv
[hvv@h hvv]$
Задавшему вопрос - а если файрвол отрубить - чего-нить изменяется?

hvv
()

А, это IPVS. http://www.linuxvirtualserver.org/docs/sysctl.html А задавшему вопрос нужно найти процесс, который не закрыл socket - он ведь наследуется после fork(), и должен быть закрыт _всеми_ процессами, в которых он виден. Есть proc, fuser, netstat -tnop... Или сделать shutdown() перед close(). Наконец, есть tcpdump, можно посмотреть сессию. Можно попробовать убить сервер и все его подпроцессы, если sockets in CLOSE_WAIT не пропадут - тогда это kernel bug.

idle ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.