程序大牛生动讲解:TCP为何要进行“三次握手”和“四次挥手”?

文源网络,仅供学习之用,如有侵权请联系删除。

关于TCP的文章,网上有很多,讲“三次握手”和“四次挥手”的文章。那些文章都很好的诠释了其原理,但是有些话语都干涩难懂,自己得反复的揣摩!

正好,今天在与朋友交流的时候,又看到有人在问TCP“三次握手”的问题:

file

file

其实,已经知道朋友肯定就能很快理解这句话的意思,但是还在摸索中的朋友呢?

下面将来讲讲,这TCP的“三次握手”和“四次挥手”到底是怎么一回事。

在很久很久以前.....

面试官:说说什么是TCP?

程序员:传输协议

面试官:UDP也是,那为什么不用UDP呢?

程序员:因为UDP把数据传输过去就不管了,就假定接收方一定能接收到,可惜真实的网络环境不会如此单纯,甚至是复杂、残酷的。

在网络环境中无时无刻出现着丢包、阻塞、乱序的情况,一个不小心,数据可能就传输不到目的地了,这个时候就只能轮到TCP了

面试官:为什么TCP就可靠了呢?

程序员:就是因为它的“三次握手”和“四次挥手”哇!

面试官(邪魅一笑):那你来讲讲吧!

程序员:那您且细听分说

三次握手

这个“三次握手”就是通信建立链接的一个过程,看下图

file

通俗点讲就是:

客户端:你好,我是客户端

服务端:你好,客户端,我是服务端

客户端:你好,服务端

也经常把这个过程叫做“请求->响应->响应的响应”

面试官:打断一下,问个问题,为什么不是两次或者四次,非得是三次呢?

程序员:嗯,不错,是个称职的面试官!

试想一下,客户端发送一个连接,由于丢包、超时,或是服务端根本就不想建立连接,那这个时候客户端怎么办?

客户端并不能知道结果,就只有重复的发送连接请求,虽然这个时候服务端接收到了,但客户端仍不知道这事,只能继续发请求。

此时此刻,服务端接收了客户端的请求,当然知道了客户端的存在,如果服务端不同意建立连接,客户端重试几次后就会放弃,没问题。

如果服务端愿意建立连接呢?这个时候就会发送响应给客户端(好了,你别叫唤了,客户端我知道你了)

file

到了这一步,就已经进行了两次握手!理论上,这个时候已经可以进行连接了,但是问题来了:

因为对于服务端来说,这个响应的过程也可能会丢包,不一定会达到客户端,甚至客户端完全挂了都是可能的。

对于另外的情况,在第一次握手的时候,由于网络问题,客户端向服务端发送了多个建立连接的请求,假设其中某一个建立成功,做了简单的通信,然后结束了连接,本来很正常,但是另外一些请求由于网络的延迟又到了服务端,服务端会认为这是一个正常的请求,接下来又建立连接。

因此两次握手会有着种种问题。

为了保证服务端的响应能正确接收,客户端还是需要告诉给服务端,我收到了服务端的响应,也就是给服务端一个“响应的响应”,这样就是三次握手了。

面试官:要是这个“响应的响应”要是也出现了丢包等问题没有送到呢?

程序员:你存心找麻烦的吧?那照你这样说你就是手握烂了,也没办法保证消息100%可靠。三次握手,保证服务端、客户端双方都确认了对方存在就足够了。

四次挥手

面试官:嗯,不错,来说说“四次挥手”又是什么吧!

程序员:建立完连接后就可以传输数据了,传输完成后则需要四次挥手来告别,过程看下图

file

面试官:这你TMD没有上一张清晰啊!

程序员:哎呀~面试时间有限,将就着看看啦!

通俗来讲就是:

客户端:服务端啊,我要和你拜拜了

服务端:好的,我知道了

这个时候,客户端说了拜拜,也不会向服务端发送数据了,这个时候服务端是否能马上关闭呢?

不可以!因为服务端可能还没处理完相应的事情,所以还是要发送数据的,这个时候的状态为等待关闭的状态,当处理完后需要继续下面步骤。

服务端:客户端,我也要和你说拜拜了

客户端:拜拜,滚吧

file

其实在这里也会存在一些问题,当客户端说“拜拜”,服务端说“知道了”,这两次是没什么问题的。

但是当客户端说“拜拜”之后就直接夺门而出,这样就出问题了,因为服务端还没说“知道了”,就算已经说了“知道了”,客户端也可能已经走了。

这个时候为了解决这些问题,TCP协议还有几个状态来处理这些问题,就如上面看的状态图。

当客户端说“拜拜”,就进入 FIN_WAIT_1 的状态,服务端收到“拜拜”的消息后,发送“知道了”,然后就进入 CLOSE_WAIT 的状态。

当客户端接收到“知道了”,进入FIN_WAIT_2,过一段时间,客户端也接收到了“客户端,我也要和你说拜拜了”,客户端就应该发送“拜拜,滚吧”,说完这句话已经就可以走了。

但是客户端发送的消息没发送成功,服务端只能重复发送“我也要和你说拜拜”,可惜的客户端已经走了,永远不会给你响应。

由于存在这种问题,TCP协议要求客户端在离开之前先等待一会会,这个等待的时间叫TIME_WAIT,这个TIME_WAIT还有另外一个作用,如果客户端说完“拜拜”之后还需要等待一段时间,如果不等待就会直接释放端口。

在前面一次连接客户端说完“拜拜”就走了,服务端不知道,不停的回复“知道了”,这时候一个新的客户端连接了,这新客户端接收到了“知道了”这是不是就特别混乱了?

所以这TIME_WAIT就特别重要了,它可以保证让迟来的TCP报文段有足够的时间被识别和丢弃。连接结束了,网络中的延迟报文也应该被丢弃掉,以免影响立刻建立的新连接。

我将面试题和答案都整理成了PDF文档,还有一套学习资料,涵盖Java虚拟机、spring框架、Java线程、数据结构、设计模式等等,但不仅限于此。

关注公众号【java圈子】获取资料,还有优质文章每日送达。

file

展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 精致技术 设计师: CSDN官方博客
应支付0元
点击重新获取
扫码支付

支付成功即可阅读