TCP建立连接过程中为什么需要“三次握手”

TCP 为什么是三次握手,而不是两次或四次?之前对此一直是模模糊糊,最近在看这方面的知识,把看到的一些比较好的解释和最近的一些理解组织一下和大家交流分享一下。

tcp

上图通俗的表现了 TCP 的三次握手,通过前两次对话证明了接收方能够听懂发送方的说的话,并能做出正确的回答,
通过第二次和第三次对话证明了发送方能够听懂接收方说的话,并且能够做出正确的回答。

可见,两个人如果要进行有效的沟通,这三次对话的过程是必须的。

也就是说:

为了保证服务端能收接受到客户端的信息并能做出正确的应答而进行前两次(第一次和第二次)握手,为了保证客户端能够接收到服务端的信息并能做出正确的应答而进行后两次(第二次和第三次)握手。

其中的重点是:

让双方都证实对方能发收。

1:A发,B收, B知道A能发

2:B发,A收, A知道B能发收

3:A发,B收, B知道A能收


在谢希仁著《计算机网络》第四版中讲:

“三次握手”的目的是“为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误”。在另一部经典的《计算机网络》一书中讲“三次握手”的目的是为了解决“网络中存在延迟的重复分组”的问题。

在谢希仁著《计算机网络》书中同时举了一个例子,如下:

“已失效的连接请求报文段”的产生在这样一种情况下:client发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达server。本来这是一个早已失效的报文段。但server收到此失效的连接请求报文段后,就误认为是client再次发出的一个新的连接请求。于是就向client发出确认报文段,同意建立连接。假设不采用“三次握手”,那么只要server发出确认,新的连接就建立了。由于现在client并没有发出建立连接的请求,因此不会理睬server的确认,也不会向server发送数据。但server却以为新的运输连接已经建立,并一直等待client发来数据。这样,server的很多资源就白白浪费掉了。采用“三次握手”的办法可以防止上述现象发生。例如刚才那种情况,client不会向server的确认发出确认。server由于收不到确认,就知道client并没有要求建立连接。”

这样就很清楚了,防止服务器端误认为已经建立连接然后一直等待而浪费资源。


然而“三次握手”就能确认一条信道是可靠的吗?

这是个经典的“两军通信”问题,假设场景是这样的:在山的两头是红军1和红军2,山上是蓝军,红军1和2都不是蓝军的对手,想打败蓝军只有一起动手。那么红军1和2如何通信才能确定双方在同一个时间动手呢?红军1的传令军成功偷偷越过大山告诉红军2,明天早上中午十二点一起动手;红军2表示赞同,但是红军1并不确定红军2是否收到了消息,贸然动手必定失败,所以红军2的传令军越过大山告诉红军1收到了消息;但是这时候红军2并不确定传令军是否成功到达红军1告诉红军1收到了消息,不敢独自动手,所以红军1只好再次派出传令军,告诉红军2我们知道你们收到消息了;问题又来了,红军1不知道传令是否成功,只有等待红军2的确认并不敢动手,红军2也只能再次派出传令军。。。最后陷入了一个死循环,那么根本问题就暴露了:永远都不能完美的达成协议。

这个问题在谢希仁著《计算机网络》中也有解释:

三次是保证双方互相明确对方能收能发的最低值。

理论上讲不论握手多少次都不能确认一条信道是“可靠”的,但通过3次握手可以至少确认它是“可用”的,再往上加握手次数不过是提高“它是可用的”这个结论的可信程度。