我们知道:
/////////////////////////////////////////////// //////////
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分钟,打印出来:
首先是然后,我用:
....
connect(192.168.1.100)
....
shutdown(socketfd,SHUT_WR);
sleep(1000);
使用wireshark转储数据包:
01 - &gt; syn
02&lt; - syn,ack
03 - &gt; ack
04 - &gt; fin,ack
05&lt; - ack
...
netstat -an | grep 192.168.1.100
运行约10分钟,它总是打印: “tcp 0 0 ... FIN_WAIT2”
来自wireshark的输出,似乎关闭和关闭没有什么不同,
但是从netstat的输出来看,它的行为是不同的。
那为什么行为不同?
答案 0 :(得分:11)
关闭套接字和执行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)。