TCP三步握手three way (or three message) handshake 是TCP核心知识点,很长一段时间内我无法理解为什么TCP建立连接需要三次通信,而不是两次或者四次或者更多次。我翻了很多问答和博客,他们说的都很有道理,但是借来的火,点不亮自己的灯。随着时间的推移终于对这个问题我有了自己的理解。
TCP握手为什么需要三次通信?
互联网这个信道并不可靠,TCP用于在不可靠的信道中进行可靠的信息传递。首先要明确的是,无论通过多少次握手都无法改变信道不可靠的事实,而如何在不可靠的信道中进行可靠的信息传递才是要解决的问题。
A无法确认B是否收到信息的情况下要确认B收到可以通过观察B的反馈做到。
也就是说B在规定时间内没有反馈那么A就认定B没有收到,A会重新发送,直到收到B的反馈。
所以在不可靠信道中交换一次信息至少需要两次通信。
在TCP握手过程中客户端要询问服务端的是你可以通信吗?服务端会回答我可以或者不可以。所以有两次信息交换,正常需要四次通信。
A → B B → A 客户端询问服务端是否可以通信的信息确保传达完成。
B → A A → B 服务端答复客户端我可以/不可以的答复信息确保传达完成。
中间的两次B → A通信可以合并为一次,所以总共就变成了三次通信。
通信过程中传递的信息具体有什么?
A → B:能听到吗?能通信吗?
B → A:能听到,能通信(回答能通信隐含的意思就是能听到)
B → A:我的回复收到了吗?
A → B:收到了
中间两次通信合并后:
A → B:能听到吗?能通信吗?
B → A:能听到,能通信(回答能通信隐含的意思就是能听到),我的回复收到了吗?
A → B:收到了
这样三次通信后完成握手。
信道可靠,握手则只需要两次通信即可完成:
A → B:能通信吗?
B → A:能
不需要确认是否可以通信:
握手是为了交换对方是否可以通信的信息,如果无需确认对方是否可以通信则无需握手,因为没有信息需要同步。
除了我的理解以下是收集的相关素材,都是原文摘抄,侵删:
-
TCP是一种可靠的传输控制协议,它必须做到两点,一是保证数据的可靠传输,二是尽可能提高传输效率,三次握手正是为了做到这两点才出现的。 -
这个问题在谢希仁版《计算机网络》里说了。三次是保证双方互相明确对方能收能发的最低值。理论上讲不论握手多少次都不能确认一条信道是“可靠”的,但通过3次握手可以至少确认它是“可用”的,再往上加握手次数不过是提高“它是可用的”这个结论的可信程度。 -
简单说,让双方都证实对方能发收。知道对方能收是因为收到对方的因为收到而发的回应。 具体: 1:A发,B收, B知道A能发 2:B发,A收, A知道B能发收 3:A发,B收, B知道A能收 -
三次握手这个说法不好,其实是双方各一次握手,各一次确认,其中一次握手和确认合并在一起 -
这个问题的本质是, 通过一个不完全可靠的信道, 最少需要几次消息传输, 信道两边的人能够对一个问题达成一致. 对于TCP来说, 无论有没有初始 序号的要求, 想要两边都同意开始传出数据, 就至少需要3次消息的交换: 0次: 显然不行 1次: A->B, A不知道B是否同意 2次: A->B, B->A. B不知道A是否收到自己的消息, 因为信道不完全可靠 3次: A->B, B->A, A->B. 两边都收到了对方的ACK, 意味着各自都了解了对方的意图, 从而可以对是否开始通信这个最简单的问题 达成一致. -
两军问题根本不能解释为什么要三次握手。两军问题的一个结论就是,在不可信的信道上,不可能实现完全可信的通信。 -
No… 三次握手的要求不是源于两边同时传输数据, 你看过Two Generals’ Problem就能明白, 三次握手作为一个协议, 并不特定于 TCP, 跟两边同时传输数据也没有关系. 请不要纠缠于什么全双工, 半连接, syn/ack这些东西上. 至于你说的把握手协议并在第一个数据包 里发送之类的, 那只是实现时的优化, 跟"三次"问题的核心没有关系. 实现是实现, 协议是协议, 这是两个东西. 你单独有个握手协议也好, 握 手包含在真正的数据包里也行, 但无论如何, 没有至少三次握手, 任何的数据交换都是不可靠的. 所以, 这个问题的本质是, 信道不可靠, 但是通信双发需要就某个问题达成一致. 而要解决这个问题, 无论你在消息中包含什么信息, 三次通信是理论上的最小值. 所以三次握手不是TCP本身的要求, 而是为了满足"在不可靠信道上可靠地传输信息"这一需求所导致的. 请注意这里的本质需求,信道不可靠, 数据传输要可靠. 三次达到了, 那后面你想接着握手也好, 发数据也好, 跟进行可靠信息传输的需求就没关系了. 因此,如果信道是可靠的, 即无论什么时候发出消息, 对方一定能收到, 或者你不关心是否要保证对方收到你的消息, 那就能像UDP那样直接发送消息就可以了.
参考
- TCP 为什么是三次握手,而不是两次或四次?
- TCP建立连接为什么是三次握手?
|