SA>Как правильно закрыть потоковый сокет, SA>что бы он после этого не висел некоторое SA>время в состоянии TIME_WAIT?
В моём понимании, в состоянии TIME_WAIT находится сокет, закрытый с одной стороны, но не закрытый с другой. Для обхода ситуации непосредственно перед close(fd) [в виндах — closesocket(fd)] вызови shutdown(fd,SHUT_RDWR) [в виндах — shutdown(fd,SD_BOTH)] — это сигнал удаленной машине, что данные больше пересылаться и приниматься вызвавшей shutdown() стороной не будут. Как следствие, select() на удаленной машине сработает, recv() вернет ноль и удаленная машина (если она правильно работает, конечно) закроет соединение —
после этого сокет из TIME_WAIT изчезнет.
Здравствуйте, SergeyAksuchenko, Вы писали:
SA>Как правильно закрыть потоковый сокет, SA>что бы он после этого не висел некоторое SA>время в состоянии TIME_WAIT?
А зачем это надо?
Дело в том, что после закрытия сокета, он продолжает какое-то время жить в системе, чтобы корректно добить пакеты, которые могли задержаться в сети, и, возможно, чтобы не использовать для вновь открываемых сокетов те же параметры, которые недавно были использованы (опять же, чтобы в них не сыпался мусор, который остался от предыдущего соединения; чтобы их не попутали, когда один конец думаеет, что соединение закрыто, а второй так не думает).
При этом сокет переходит в какое-то специфическое состояние, наверное это и есть TIME_WAIT.
В TIME_WAIT некоторое время будет находиться тот, кто инициировал закрытие
сокетного соединения. Если ты хочешь обойти EADDRINUSE то посмотри
SO_REUSEADDR
> В моём понимании, в состоянии TIME_WAIT находится сокет, > закрытый с одной стороны, но не закрытый с другой. > Для обхода ситуации непосредственно перед close(fd) [в виндах — closesocket(fd)] > вызови shutdown(fd,SHUT_RDWR) [в виндах — shutdown(fd,SD_BOTH)] — это сигнал > удаленной машине, что данные больше пересылаться и приниматься вызвавшей > shutdown() стороной не будут. Как следствие, select() на удаленной машине > сработает, recv() вернет ноль и удаленная машина (если она правильно работает, > конечно) закроет соединение - > после этого сокет из TIME_WAIT изчезнет.
Именно так и делаю, но не помогает
Поэтому и спросил.
Сокет закрытый локально (сказав ему closesocket или shutdown(SD_SEND), тем самым отослав FIN на другую сторону), но не получивший FIN с другой стороны находится в FIN_WAIT_n (FIN_WAIT_1 если еще не получил ACK на совой FIN и в FIN_WAIT_2 в противном случае).
Если сокет был закрыт удалено, но локально еще не закрыт, то он будет находиться в состоянии CLOSE_WAIT.
В RFC 793 объясняется, для чего, после закрытия, одна из сторон остается в TIME_WAIT 2MSL (Maximum Segment Lifetime).
Здравствуйте, av, Вы писали:
SA>>Как правильно закрыть потоковый сокет, SA>>что бы он после этого не висел некоторое SA>>время в состоянии TIME_WAIT?
В состояние TIME_WAIT попадает тот сокет который первым инициировал разрыв соединения,
после того, как принял подтверждение на отосланный сегмент FIN, получил FIN от собеседника
и послал ему подтверждение.
и как уже говорилось выше, это состояние используется для того, чтобы дождаться истечения времени жизни дублированных пакетов и обеспечить надежность разрыва соединения.
Насколько я знаю, даже изменить время состояния TIME_WAIT нельзя это зависит от реализации, обычно от 30 сек, до 2х минут.
Ни close ни shutdown ничего не меняют.
Здравствуйте, SergeyAksuchenko, Вы писали:
SA>Как правильно закрыть потоковый сокет, SA>что бы он после этого не висел некоторое SA>время в состоянии TIME_WAIT?
SA>netstat -a -n
Сказать peer'у, чтобы он закрыл.
А если закрываешь сам, то нет шансов.
Все-таки по стандарту TCP инициатор закрытия должен подержать у себя TIME_WAIT некоторое время.
Другой дело, что можно через sysctl уменьшить это самое время.
Скажи какая ОС, скажу каким sysctl'ем.
где <number> меньше текущего значения...
уменьшай до тех пор, пока не надоест...
в принципе, это переменная имеет глобальное значение на поведение стэка, так что в контексте инета не советую уменьшать ее больше чем в 10 раз.
Хотя если ты работаешь не с dial up internet clients, а с какими-нибудь приложениями в локальной сети, то хоть до 30 уменьшай.
Здравствуйте, av, Вы писали:
с>> sysctl -w net.inet.tcp.msl=<number>
av>Thnx a lot! av>Скажи вот что, плиз: это вещь постоянная или ее при каждой загрузке ставить av>надо?