TCP两次握手

TCP的三次握手已经被说烂了,TCP为何要三次握手?为何不两次握手也有很多说法。对于这些类似的问题,最好的办法是看RFC

常规思路,由面到点

  • 两军问题

在不可靠通信下,两军想要达到状态一致是无解的。因为在不可靠信道下,一边状态的确认需要另一边的回复(ACK),而另一边回复时再次面临不可靠信道问题,这样就回到了问题的最初,无限递归

既然“两军问题”无解,TCP也面临此问题,为何TCP还能可靠传输数据呢?

两军A,B为达成一致状态,A需要知道B是否收到信息(A-->B),B需要知道A是否知道B已经收到信息(B给ACK)(B-->A)

但对于TCP,A只需要知道B有没有收到信息,并不关心B是否知道A已经知道B已经收到信息(这里语言表达不太友好...),只要网络不是100%不可靠,这个是可以实现的(例如通过超时重传机制辅助)。即:TCP并不需要两边状态一致

感觉有人要打我脸了,用过钉钉的人会说,A发送给B一条消息,B看到后会显示“已读”,你看,在不可靠的网络上这不状态一致了么?额。。。

这里有两个惯性思维

1.一般用户甚至程序员会理所当然的认为网络,通信软件是可靠的(这个只能说国内的公网还不错),认为B收到A的消息并且看了以后,A那端一定会显示“已读”

2.上帝视角。A和B是同时在你的脑袋里虚拟的角色,B通过你这个上帝得知了A的情况而不是通过“不可靠信道”

这是环境使然,打破这个只能靠逻辑,或者换一个环境

我们换一个环境:

在战区,电磁干扰很严重,A给B发送了一条消息,虽然A端显示已读,但这时候B就懵逼了:A有没有收到?(还深信不疑只要B看了A就一定收到且显示为“已读”么?)

当然此时很多人还是会质疑我:平时约朋友,A发消息:晚上5.见,B回消息:好,5.见。这事就定了啊,实际也就是这样约到的啊?!。。。

这里的问题在于:

1.国内的公网大多数情况下是可靠的,尤其对于IM这种消息量不大的应用体现更为明显,所以给人造成刻板印象,A发出去的B一定能收到,A也一定能收到B给的ACK  

2.事情本身的风险很小

我们用“笨方法”分析

A ----> B  (A向B发送消息:晚上5.见)

B ----> A  (B收到消息回复ACK

A收到ACK并显示“已读”,此时A,B各自的状态为:

A:知道B收到了消息

B:不知道A是否收到ACK,即:不知道A是否知道B收到消息“晚上5.见”

设定一个场景,A,B必须同时在5.约定的地点出现,否则单方出现的会被出卖,即:任何一方都不能冒险,必须100%确定

由于B 不知道 A 是否知道B已经收到消息,所以没法100%确定,所以B不会赴约

A也知道B会这么想,所以A也不会赴约

继续:

B ---->  A   (B向A发送消息:好,5.见)

A ---->  B   (A向B发送ACK)

B收到ACK并显示“已读”,此时A,B各自的状态为:

A:不知道B是否收到ACK,即:不知道B是否知道A收到消息“好,5.见”

B:知道A收到了消息

综合上面的情况:

A:确定:B收到了消息“晚上5.见”,确定:B不确定A知道B收到消息“晚上5.见”,不确定:B知道A收到消息“好,5.见”,

B:确定:A收到了消息“好,5.见”,确定:A不确定B知道A收到消息“好,5.见”,不确定:A知道B收到消息“晚上5.见”

此场景“不确定”等价于“没有,不,没发生”

A的视角:B收到了消息“晚上5.见”,B没有对发送的消息“好,5.见”显示已读

B的视角:A收到了消息“好,5.见”,A没有对发送的消息“晚上5.见”显示已读

等价于

A的视角:B收到我发送的消息“晚上5.见”,B认为:A认为B发送的消息“好,5.见”显示发送失败,B认为我发送的消息“晚上5.见”显示发送失败

B的视角:A收到我发送的消息“好,5.见”,A认为:B认为A发送的消息“晚上5.见”显示发送失败,A认为我发送消息的“好,5.见”显示发送失败

  • “ISN”

如果是两次握手,B收到A的SYN包后状态即为:established,此时B再给A发送一个SYN+ACK包,由于此时B已经为ESTABLISHED所以可以向A发送数据,如果数据包先于SYN+ACK包到达A,A就尴尬了,A没有收到B的ISN,没法判断这些数据包是否能用(< ISN 该直接丢弃),对于这样一个优雅的牛逼协议,这是没法容忍的

如果是三次握手,B收到A的SYN包后状态即为:SYN_RECV,是没法发送包的

但有一点是相同的,无论是SYN_RECV或者ESTABLISHED,都是一种等待状态,都需要发送数据包确认对方是否还在

  • 四次握手

三次握手本质是四次握手的简化

1.A ----> B (SYN,ISN)

2.B ----> A  (ACK)

3.B ----> A  (SYN,ISN)

4.A ----> B  (ACK)

2和3合并后成了“三次握手”,四次握手建立连接和四次握手关闭连接是对应的,体现了全双工

猜你喜欢

转载自www.cnblogs.com/deepscenery/p/10747634.html