tcp堆栈如何区分关闭和关闭?

我们知道:

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

close()将终止tcp连接上的两个方向

shutdown()可以阻止一个或两个方向的通信

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

在这里,让我困惑的是tcp stack如何区分它们?

我写了一个示例程序:

首先我使用:

....
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 03 – > ack

04 – > fin,ack

05< - ack … netstat -an | grep 192.168.1.100 运行大约10分钟,它总是打印:
“tcp 0 0 … FIN_WAIT2”

从wireshark的输出来看,关闭和关闭似乎没有什么不同,

但是从netstat的输出来看,它的行为是不同的.

为什么行为不同?

最佳答案
关闭插座和关机(SHUT_RDWR)之间的线路没有区别.这两种情况都会导致TCP堆栈发出FIN并停止接受来自另一端的数据包.唯一的区别在于你的程序:关闭后文件描述符仍然有效,但关闭后却没有.可以肯定的是,除了关闭它之外,关闭后仍然无法使用仍然有效的文件描述符,但它仍然有效.

在您的情况下,您使用SHUT_WR,而不是SHUT_RDWR,因此您的套接字仍然准备从另一端接收数据.但是您的服务器不会发送任何数据.如果服务器在客户端关闭结束后发送了一些数据,您会看到关闭和关闭(SHUT_WR)之间的区别. close()客户端将使用RST响应服务器的数据,而关闭(SHUT_WR)客户端将接受服务器的数据并对其进行确认.关闭(SHUT_RDWR)客户端的行为与close()客户端相同.

在大多数客户端 – 服务器TCP协议(例如HTTP)中,一旦从客户端收到FIN,服务器就会终止其连接的结束.因此,对于这些协议,无论客户端半关闭还是完全关闭套接字都没有太大区别,因为服务器无论如何都会立即关闭其连接的末尾.我可以看到你的服务器没有这样的行为,因为我没有看到它发送自己的FIN(只有你的客户端发送FIN).

转载注明原文:tcp堆栈如何区分关闭和关闭? - 代码日志