как стек tcp различает закрытие и выключение? - PullRequest
3 голосов
/ 22 марта 2012

Как мы знаем, что:

/////////////////////////////////////////////////////////////

close () прервет оба направления по TCP-соединению

shutdown () может заблокировать связьв одном или обоих направлениях

///////////////////////////////////////////////////////////////

вот, что меня озадачило, как стек tcp может отличить их друг от друга?

Я написал пример программы:

сначала я использую:

....
connect(192.168.1.100) //there is a server process running in 192.168.1.100
....
close(socketfd);
sleep(1000);

затем я использую wireshark для вывода пакетов:

01 -->syn

02 <--syn,ack

03 -->ack

04 -->fin,ack

05 <--ack

netstat -an | grep 192.168.1.100

Я запустил его в течение 5 минут, сначала он напечатал:

"tcp 0 0 ... FIN_WAIT2", затем примерно через 2 минуты ничего не выводится, кажется, что соединение было разорвано.

затем я использую:

....
connect(192.168.1.100)
....
shutdown(socketfd,SHUT_WR);
sleep(1000);

используйте wireshark для выгрузки пакетов:

01 -> syn

02 <- syn,ack </p>

03 -> ack

04 -> плавник, ack

05 <- ack </p>

...

netstat -an | grep 192.168.1.100

запустить его около 10 минут, он всегда печатает: "tcp 0 0 ... FIN_WAIT2"


с выхода wireshark, кажется, нетотличается для закрытия и выключения,

, но из вывода netstat его поведение отличается.

так почему поведение отличается?

1 Ответ

11 голосов
/ 22 марта 2012

На проводе нет разницы между просто закрытием сокета и выполнением shutdown(SHUT_RDWR). Любой из них заставит стек TCP испускать FIN и прекратит принимать пакеты с другого конца. Единственная разница в вашей программе: после shutdown дескриптор файла остается действительным, а после close - нет. Безусловно, вы не можете многое сделать с все еще действующим файловым дескриптором после shutdown, кроме его закрытия, но, тем не менее, он действителен.

В вашем случае вы используете SHUT_WR, а не SHUT_RDWR, поэтому ваш сокет по-прежнему готов к приему данных с другого конца. Но ваш сервер не отправляет никаких данных. Вы бы увидели разницу между close и shutdown(SHUT_WR), если бы ваш сервер отправил некоторые данные после того, как клиент закрыл свой конец. Клиент close() будет отвечать на данные сервера с помощью RST, тогда как клиент shutdown(SHUT_WR) будет принимать данные сервера и подтверждать их. Клиент shutdown(SHUT_RDWR) будет вести себя так же, как клиент close().

В большинстве протоколов TCP-клиент-сервер (например, HTTP) сервер в любом случае завершит свое соединение, как только получит FIN от клиента. Таким образом, с этими протоколами не имеет большого значения, будет ли клиент полузакрывать или полностью закрывать сокет, потому что сервер все равно быстро закроет свой конец соединения. Я вижу, что ваш сервер ведет себя не так, потому что я не вижу, что он отправляет свой собственный FIN (только ваш клиент отправляет FIN).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...