Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how tcp stack distinguish close and shutdown?

Tags:

tcp

As we known that:

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

close() will terminate both directions on a tcp connection

shutdown() can block communication in one or both directions

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

here,what puzzled me is how tcp stack can tell them apart?

I have write an example program:

firstly I use :

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

then I use wireshark to dump the packets:

01 -->syn

02 <--syn,ack

03 -->ack

04 -->fin,ack

05 <--ack

netstat -an |grep 192.168.1.100

I have run it for about 5 minutes, it print:

"tcp 0 0 ... FIN_WAIT2 " at first,then after about 2 minutes there is no output,seems that the connection has been destroyed.

then, I use :

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

use wireshark to dump the packets:

01 -->syn

02 <--syn,ack

03 -->ack

04 -->fin,ack

05 <--ack

...

netstat -an |grep 192.168.1.100

run it for about 10 minutes, it always print: "tcp 0 0 ... FIN_WAIT2"


from the output of wireshark ,it seems there is no different for close and shutdown,

but from the output of netstat ,its behaviour is different.

so why the behaviour is different?

like image 683
camino Avatar asked Dec 22 '22 00:12

camino


1 Answers

There is no difference on the wire between just closing the socket and doing shutdown(SHUT_RDWR). Either will cause the TCP stack to emit a FIN and stop accepting packets from the other end. The only difference is in your program: after shutdown the file descriptor remains valid, but after close it doesn't. To be sure, you cannot do much with the still-valid file descriptor after shutdown besides closing it, but it is valid nonetheless.

In your case you use SHUT_WR, not SHUT_RDWR, so your socket is still prepared to receive data from the other end. But your server doesn't send any data. You would see a difference between close and shutdown(SHUT_WR) if your server sent some data after the client had closed its end. The close() client would respond to the server's data with RST whereas the shutdown(SHUT_WR) client would accept the server's data and ACK it. A shutdown(SHUT_RDWR) client would behave the same as the close() client.

In most client-server TCP protocols (like HTTP for instance), the server will terminate its end of the connection anyway as soon as it receives a FIN from the client. So with those protocols it doesn't make much of a difference whether the client half-closes or full-closes the socket because the server will promptly close its end of the connection anyway. I can see that your server does not behave like this though, because I don't see it sending its own FIN (only your client sends a FIN).

like image 53
Celada Avatar answered Jan 08 '23 08:01

Celada