花样趣谈TCP面试的那些事儿

TCP有什么好谈的吗?既没有SpringCloud,MQ这些技术有逼格,也没有Redis,MySql优化这些技术实用。

是的,我也一度认为这些技术离程序员屌丝们很远,直到面试的只是吃过亏,而且可恨的是由于我的不重视,我甚至在同一个坑里面掉过两次。

与其说是喜欢装逼,喜欢这些协议,还不如说是为了应付面试不得不把这些知识恶补,为了让自己记忆更深刻,把这些以文字的方式记录下。

从面试题开始谈起

做了两年开发,说真的redis,springcloud这些技术吧工作也算用过,一些工作上的问题解决得游刃有余,小组长一个,下面带5个小兵,对于其他伙伴来说我还是算春风得意。

人往高处走,水往低处流,已经有三年左右的工作经验可以去挑战下高级软件工程师,不说面试架构师吧,总归可以尽量往上面靠。

让人尴尬的是,一面试一个问题就让我尴尬了。

说一下TCP的三次握手过程?

解释一下TCP的四次挥手?

有点小尴尬,我真的答不上来,这是第一次面试,不算太好,其他的问题也算勉勉强强,对于TCP的这面试题吧,只算众多面试题种的一个,我也并没在意他。

接下来一次面试

为什么TCP握手需要三次?

这次就不是小尴尬了,因为上次面试已经吃过亏,但这次显然我又答不上来了,我连TCP三次握手是什么都答不上,更别说为什么需要3次呢,第二次面试按理我准备更充分,但就这插曲,让我整个面试的状态很差,感觉比第一次面试还让人不尽人意。

谈谈TCP是什么

两次掉坑里得经验让我不得不重视了TCP这玩意,其实TCP说完全陌生吧,还真不是,TCP/IP这个词我就无数次听过,用过,但具体的TCP过程吧,我还是恶补后才知道。

简单来说TCP是传输协议,与此相类似的还有UDP,UDP是把数据传输过去就不管了,就假定接收方一定能接收到,可惜真实的网络环境不回如此单纯,甚至是复杂,残酷的

在网络环境中无时无刻出现着丢包,阻塞,乱序的情况,一个不小心,数据可能就传输不到目的地了,就个时候TCP就登场了。那么TCP为什么要更可靠呢? 因为需要三次握手,四次挥手了。

TCP的三次握手

要进行通信,最先得建立一个链接,那么我们就先来看下链接建立的过程,这个TCP的建立过程我们通常叫做三次握手,整个过程如下图所示。

看明白了吗?估计是看不明白,先不说那么复杂,先用生活的故事来说应该比较好懂。

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

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

客户端:你好,服务端

这样看好理解多了,我们也经常把这个过程叫做“请求->响应->响应的响应”,这样就解决了TCP三次握手是什么的问题。

那么继续往后看,上面的面试题还问到为什么是三次握手呢?两次或者四次不行吗?

其实这问题的解答还是要回到网络的不可靠上,客户端发送一个连接,由于丢包、超时,甚至是服务端根本就不想建立连接这个时候客户端怎么办?客户端并不能知道结果,只有重复的发送,直到请求到了服务端,虽然这个时候服务端接收到了,但客户端却不知道这事,A既然可能继续发请求。

此时此刻,服务端接收了客户端的请求,当然知道了客户端的存在,如果服务端不同意建立连接,客户端重试几次后就回放弃,没问题。如果服务端愿意建立连接呢?这个时候就回发送响应给客户端(好了,你别叫唤了,客户端我知道你了)

仔细回顾,现在已经两次握手了,客户端呼叫了几次服务端,服务端不耐烦的也回答了客户端还在,这样看已经没问题了,视乎两者已经建立了连接,为什么还不够呢?

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

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

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

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

你当然还会收,如果“响应的响应”也没正常送到呢?是不是要来个“响应的响应的响应”呢?这就是四次握手呢?继续下去可以是十次握手,一百次握手,你就是手握烂了,也没法保证消息100%可靠,因此三次握手,保证服务端、客户端双方都确认了对方存在就足够了。

TCP的四次挥手

建立完连接后就可以传输数据了,传输完成后需要四次挥手来告别,四次挥手的过程如下图所示。

依然是看不懂,继续举例来说

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

服务端:好的,我知道了

这个时候,客户端说了拜拜,也不会向服务端发送数据了,这个时候服务端是否能马上关闭呢?不可以!因为服务端可能还没处理完相应的事情,所以还是要发送数据的,这个时候的状态为等待关闭的状态,当处理完后需要继续下面步骤。

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

客户端:拜拜,滚吧

这就是四次挥手,整个过程下来连接就关闭了,这就够了吗?看上去挺好的。

再来看下,当客户端说“拜拜”,服务端说:“知道了”,这两次挥手是没什么问题的,因为在这个之前,两者是相处得挺好的

但可恨的是,可能客户端说“拜拜”之后就直接夺门而出,这样就出问题了,因为服务端还没说“知道了”,就算已经说了“知道了”,客户端可能已经走了,这个时候服务端该怎么办呢?

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

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

当客户端接收到“知道了”,进入FIN_WAIT_2,过一段时间,客户端也接收到了“客户端,我也要和你说拜拜了”,客户端就应该发送“拜拜,滚吧”,说完这句话已经就可以走了,但是客户端发送的消息没发送成功,服务端只能重复发送“我也要和你说拜拜”,可惜的客户端已经走了,永远不会给你响应。

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

在前面一次连接客户端说完“拜拜”就走了,服务端不知道,不停的回复“知道了”,这时候一个新的客户端连接了,这新客户端接收到了“知道了”这是不是就特别混乱了?所以这TIME_WAIT就特别重要了,他可以保证让迟来的TCP报文段有足够的时间被识别和丢弃。连接结束了,网络中的延迟报文也应该被丢弃掉,以免影响立刻建立的新连接。

如果需要Java架构进学习资料(文档+视频)包括Dubbo、Redis、Netty、zookeeper、Spring cloud、分布式、高并发等架构技术资料的童鞋关注后私聊我喔

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值