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

cam*_*ino 3 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);
Run Code Online (Sandbox Code Playgroud)

然后我使用wireshark来转储数据包:

01 -->syn

02 <--syn,ack

03 -->ack

04 -->fin,ack

05 <--ack
Run Code Online (Sandbox Code Playgroud)

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);
Run Code Online (Sandbox Code Playgroud)

使用wireshark转储数据包:

01 - >同义词

02 < - syn,ack

03 - >确认

04 - > fin,ack

05 < - ack

...

netstat -an | grep 192.168.1.100

运行大约10分钟,它总是打印:"tcp 0 0 ... FIN_WAIT2"


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

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

为什么行为不同?

Cel*_*ada 11

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

在您的情况下,您使用SHUT_WR,而不是SHUT_RDWR,因此您的套接字仍然准备从另一端接收数据.但是您的服务器不会发送任何数据.你会看到一个差异之间closeshutdown(SHUT_WR)如果你的服务器发送了一些数据在客户端已经关闭了其结束之后.该close()客户端将在服务器的数据进行响应RST,而shutdown(SHUT_WR)客户端将接受服务器的数据和ACK它.一个shutdown(SHUT_RDWR)客户会表现得一样的close()客户端.

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