TCP 端点如何知道另一个端点是关闭了连接的两半还是只关闭了一个?

Posted

技术标签:

【中文标题】TCP 端点如何知道另一个端点是关闭了连接的两半还是只关闭了一个?【英文标题】:How does a TCP endpoint know whether the other endpoint has closed both halves of the connection or only one? 【发布时间】:2012-12-26 22:02:00 【问题描述】:

考虑在两个 TCP 端点之间建立的 TCP 连接,其中一个端点调用:

    close(): 在这里,不允许进一步读取或写入。

    shutdown(fd, SHUT_WR): 这会将全双工连接转换为单工连接,其中调用 SHUT_WR 的端点仍然可以读取。

但是,在这两种情况下,FIN 数据包都会通过线路发送到对等端点。那么问题来了,接收到 FIN 的 TCP 端点如何区分对方使用了close() 还是SHUT_WR,因为在后一种情况下它应该仍然可以发送数据?

【问题讨论】:

我猜答案是:不能;它需要由协议指定。 “需要协议指定”是什么意思? 如,(不是真正的规范)“如果服务端收到了connection:keep-alive这个header,那么半关闭的连接应该被解释为完全关闭。否则,允许发送方通过关闭他的连接部分来指示请求的结束。” 类似地,如果 TCP 端点执行了 shutdown(fd, SHUT_RD) ,那么线路上的消息交换就会发生。在线路上没有任何消息交换的情况下,对等端点如何知道另一个端点无法读取连接上的数据并应该停止发送? @VivekGupta:However, in both the cases FIN is sent on the wire to the peer endpoint.你怎么知道的? 【参考方案1】:

基本上,答案是,没有。 或者,唯一的通用方法是尝试发送一些数据,看看你收到的是 ACK 还是 RST回应。

当然,应用程序协议可能会为连接的一侧提供某种机制,以提前表明它不再希望接收更多数据。但是 TCP 本身并没有提供任何这样的机制。

【讨论】:

这应该是TCP握手机制的缺陷吗? 如果您认为需要这样的功能,这只是一个缺陷。一般来说,设计你的应用程序协议既简单又好习惯,这样一开始就不会出现这种情况(一方想要发送数据但另一方不想接收),而不是依赖于底层传输层(无论是 TCP 还是其他东西)来处理它。

以上是关于TCP 端点如何知道另一个端点是关闭了连接的两半还是只关闭了一个?的主要内容,如果未能解决你的问题,请参考以下文章

WebSocket - 关闭框架

Google应用引擎TCP连接失败

是否可以在同一端口上的 HTTP 中创建另一个端点?

“找不到具有名称的端点元素...”

浅析——SCTP协议(转)

WCF Net.tcp 仅在本地失败