Linux: socket close() vs shutdown()

10
在Linux中,shutdown()函数可以使用参数SHUT_RD、SHUT_WR或SHUT_RDWR来关闭通信通道的部分功能。但是就TCP消息发送给对等端而言,它是如何工作的呢?
在TCP状态机中,关闭操作以四次握手的方式进行。
(1)           (2)
FIN---------->

   <----------ACK
   <----------FIN

ACK----------->

当我执行shutdown(sock, SHUT_RD)或shutdown(sock, SHUT_WR)时,它会发送什么样的消息?
3个回答

18
  1. shutdown(sd, SHUT_WR)发送一个FIN,对等方将以ACK响应。任何进一步尝试写入套接字的操作都将产生错误。但是,对等方仍然可以继续发送数据。

  2. shutdown(sd, SHUT_RD)在网络上不发送任何内容:它只是条件性地使本地API在套接字上的任何后续读取返回EOS。当在已经关闭读取的套接字上接收到数据时的行为取决于系统:Unix将ACK并将其丢弃;Linux将ACK并缓冲它,这最终会使发送方停滞;Windows将发出RST,发送方会看到“连接被对等方重置”的消息。


1

FIN数据包不需要对称。当本地写入器关闭套接字时,每个端点都会发送FIN。


如果 Host1 执行 SHUT_RD 操作会怎样?那么就不会发送任何东西,对吗?如果对等方 Host2 发送了一条消息,会发生什么?HOST1 会回复 RST,还是只是忽略它? - wei
我认为它应该发送一个RST,但是我太懒了不想测试。请注意,你无法从读取端做任何事情来强制网络上的另一台主机发送任何数据包,因此我怀疑TCP实现在这方面可能会有所不同... - Andy Ross
是的,完全正确。所以如果HOST1回复一个RST,那么HOST2会关闭它的套接字,因为HOST2不知道HOST1发生了什么,并且会将这个RST视为常规的RST吗?然后如果HOST2关闭套接字,那么留下的HOST1的WRITE一半将不再工作,对吧? - wei
4
当在已关闭读取的套接字上接收数据时,行为因系统而异:Unix会确认并丢弃它;Linux会确认并缓存它,最终会导致发送方停滞;Windows会发出RST信号,发送方会将其视为“对等方重置连接”。 - user207421
@EJP,谢谢您为我澄清。不过,我不确定如何将评论视为答案。 - wei

0

使用写端关闭并发送 FIN,然后关闭套接字将会关闭套接字。因此,任何尝试发送关闭套接字的操作都将导致 RESET 数据包。

我遇到了一个有趣的问题,其中发件人发送: Packet A 发送 Packet B 发送 关闭写入 FIN 关闭读取 关闭套接字

但是接收方接收顺序错误: Packet A 包含 FIN 的数据包 Packet B 来自接收方的 ACK,这导致连接重置。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接