文章图片出处:TCP “三次报文握手,四次报文挥手”详解_wenzi嵌入式软件的博客-CSDN博客_tcp握手报文u
推荐大家详细阅读上面链接的文章,受益匪浅
三次握手
TCP连接为什么要三次握手?多一次少一次又怎么了?这个问题的前提是,计算机创建和保持TCP连接,都要消耗计算机资源。如果对方没准备好、或是不想跟我连接,那我就要立即断掉TCP连接的相关工作,省得浪费资源。还有个前提,TCP是被设计为可靠的连接,即我发消息你能收到,你发消息我能收到,且接收到的消息顺序不错乱。
在上述两个前提下,我们可以化身为客户端计算机A,我们要与服务器端B互发消息。我们就想了,我如何确定B能与我正常通信?这就像我们打电话,我们打电话是要说一件正事,但说正事前,我们要先保证对方能听到你的声音,且对方的声音我也听得到。这个跟我们的诉求一样,对于客户端A来说:
A发送:B你能收到我的消息么?
B发送:收到了,你能收到我的消息么?
如果A收到了B的消息,那对A来说,B是可以正常为我服务的。
这时我们就想了,那就是两次握手就行了。注意了,像刚才说的,对于A来说,A可是安心了,我发的你能接到,你还能回复我。但B可没安心,B只发了一句话,它也不知道A收到了没有,B可不能这么粗略的就浪费计算机资源创建并保持着一个TCP连接。我们可以想像,有人打了个电话给你:
他说:你能听到我声音么?
你说:听得到,你能听到我的么?
结果他上厕所(这个结合文章开头推荐的文章里的超时重传)去了,难道你就一直保持通话浪费电量么?
所以我们也要让B安心,即B发给A的消息,A能收到且A能正常回复B,对B来说A才可用,B才能创建TCP连接。
那么我们通过以上分析,就知道客户端A与服务端B创建可靠连接,需要A发一条,B基于此回复一条;B发一条,A基于此回复一条,合并起来一共三条,即三次握手。我们可以结合下面这张图片,可以看到,A收到B回复后,即创建了TCP连接,因为对于A来说,B已经可用了。B也同理,收到A的回复后,才信任A。
A发一条消息给B,B回复A,为了实现A知道B回复的是自己的哪个问题,且知道这是第几句话(同理B也需要知道A的消息的顺序性),我们可以想像我们要这样设计TCP:
A发的第一条消息:这是一条TCP连接请求(SYN=1),顺序是1(seq=x)
B收到A消息后回复:这也是一条TCP连接请求(SYN=1),我收到你的消息了(ACK=1),顺序是1(seq=y),我希望收到你的消息2(ack=x+1)
A发的第二条消息:我收到你的消息1了(ACK=1),这是我的消息2(seq=x+1),我希望收到你的消息2(ack=y+1)
以上就是大致的思路,可以看到,每个参数都是TCP设计时必不可少的(参数是否可合并的细节此处没追究,猜测是TCP设计时已经精简到最少参数了)
写到这,我们可能会想,为什么第三次握手时,不直接顺带着传送数据呢?而不仅仅是消息确认。此处我没有详细查找资料,我猜测传送数据会延长TCP创建时间,TCP毕竟是标准协议,在一套标准里,创建连接时间保证最优才是合理的。如果我们仿照TCP,自己做一套客户端服务端的可靠传输协议,且已知每次传输数据量极少,那我觉得在第三次握手的同时携带数据,也是可以考虑的。
四次挥手
有了三次握手时讲到的“信任”机制,我们可以想像,A释放TCP连接的条件是什么?
A表明:我要释放TCP连接
B回复:我收到你的分手请求了,我同意
此时对于A来说,连接其实就可以立马释放掉了。由于B此时可能还有苦水要跟A倾诉,所以A只能进入【终止等待】,直到苦水倾诉完,则断掉TCP连接。也由于B要倾诉苦水,所以B无法像建立连接时一样,把第2、3条消息重合,所以是四次挥手。
A挥手:我这条消息是分手请求 (FIN=1),你的上条回复我收到了(ACK=1),我此条消息的顺序是u(seq=u),想要收到你的顺序v的消息(ack=v)
B回复:你的分手消息我收到了(ACK=1),我此条消息的顺序是v(seq=v),希望收到你的u+1顺序的消息(ack=u+1)
......
B回复:这也是一条分手消息 (FIN=1),你的上条消息我收到了(ACK=1,注:这个参数是TCP要求必传的,虽然此处看着没什么意义),我此条消息的顺序是w(seq=w),希望收到你的u+1顺序的消息(ack=u+1)
A挥手:你的分手消息我收到了(ACK=1),我此条消息的顺序是u+1(seq=u+1),希望收到你的w+1顺序的消息(ack=w+1)
以上。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。