我们知道:
////////////////////////////////////////////////// ///////
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,因此您的套接字仍然准备从另一端接收数据.但是您的服务器不会发送任何数据.你会看到一个差异之间close和shutdown(SHUT_WR)如果你的服务器发送了一些数据在客户端已经关闭了其结束之后.该close()客户端将在服务器的数据进行响应RST,而shutdown(SHUT_WR)客户端将接受服务器的数据和ACK它.一个shutdown(SHUT_RDWR)客户会表现得一样的close()客户端.
在大多数客户端 - 服务器TCP协议(例如HTTP)中,一旦从客户端收到FIN,服务器就会终止其连接的结束.因此,对于这些协议,无论客户端半关闭还是完全关闭套接字都没有太大区别,因为服务器无论如何都会立即关闭其连接的末尾.我可以看到你的服务器没有这样的行为,因为我没有看到它发送自己的FIN(只有你的客户端发送FIN).