记住:TCP不是轮询的

TCP 无法将连接的丢失立即通知应用程序,我们下面就探讨为什么 TCP 不提供这种通知机制,不这么做的优点和缺点,以及应用程序程序员必须完成哪些工作以检测连接的丢失。

为什么不设计连接丢失即时通知机制

显然,对可用网络带宽的耗费是 TCP 不提供连接丢失即时通知的原因之一。大部分应用程序都不需要即时通知,因此不应该为之付出降低带宽的代价。如果应用程序确实需要及时获得对等实体不可达的信息,可以像稍后讨论的那样,实现自己的丢失发现机制。比方说 HTTP 只支持客户端向服务端主动通信,服务端却不可以主动给客户端推送消息。如果非要服务端主动和客户端通信,就可以利用轮询机制,即让客户端定时发送消息给服务端,服务端再给客户端回消息来营造服务端主动和客户端通信的假象。尽管轮询机制是常见的思想,但是非常容易被替代,因为对资源有太多不必要的消耗,这就是为什么 WebSocket 有出现的必要。

但 TCP 不提供连接丢失即时通知最重要的原因与其主要设计目标之一有关:出现网络故障时维护通信的能力。国防部赞助的一项研究要提供一种即使在发生战争或自然灾害这种严重网络损坏的情况下,也能维护可靠网络通信的网络协议,TCP就是这种研究的产物。通常,网络故障只是暂时的,有时路由器会为连接找到另一条路径。TCP允许临时的连接丢失,但通常可以在终端应用程序还没意识到的情况下处理好这些网络中断

强制应用程序去监视网络的缺点在于必须将代码构建到每个(需要它的)应用程序中去,如果实现上考虑不周,就会浪费带宽,还可能产生一些对网络及其他用户有不利影响的行为。但也有人持不同的意见,认为应该在应用程序去监视网络,就可以对其进行精细调整以适应应用程序的需要,并尽可能地与应用程序协议无缝结合。

如何在应用层实现连接丢失即时通知机制

这里不介绍POSIX套接字提供的保持活跃机制,而是着重介绍心跳信号机制。书里面介绍两种实现方式:

  • 规定通信格式来确定客户端的存活,即只需要为心跳报文增加一个报文类型
    1. 定义心跳消息类型:在协议中定义一个特殊的消息类型,例如 HEARTBEAT
    2. 定期发送心跳消息:客户端和服务器定期发送心跳消息以表示连接仍然活跃
    3. 接收并处理心跳消息:接收方收到心跳消息后,更新最后一次接收到心跳消息的时间
  • 没有规定通信格式,那么通信的数据中就无法找到客户端发送的消息,心跳信号机制也就失效。对于没有规定通信格式的这种,启动一个独立的连接来发送和接受心跳信号
    1. 建立心跳连接:客户端和服务器建立一个独立的连接专门用于心跳信号
    2. 定期发送心跳消息:在心跳连接上定期发送心跳消息
    3. 接收并处理心跳消息:接收方在心跳连接上接收并处理心跳消息

⭐️内容取自译者陈涓、赵振平《TCP/IP高效编程:改善网络程序的44个技巧》,仅从中取出个人以为需要纪录的内容。不追求内容的完整性,却也不会丢失所记内容的逻辑性。如果需要了解细致,建议读原书。