面试官:说说TCP三次握手过程,如果两次握手会怎么样?
让我们来看一个故事,读完这个故事,我相信你和面试官的对话会非常愉快。
网络帝国的崛起
随着时间的流逝,计算机帝国的子民耐不住寂寞,他们好想去外面的世界看看,去其他的计算机家中串串门,他们经常抱怨,为什么那些官员可以互相聊天,而我们只能自己对自己说话.
这些抱怨传到了计算机国王的耳中,国王也很头痛啊,他也想让子民相互沟通,畅聊无阻,可是不同计算机运行着不同的操作系统,他们在表达同一种信息的时候采用的方式千差万别,很难统一啊,官员们也是费了好大劲才把那么几个操作系统的通信搞定,更何谈万千子民了.
这一次,国王召开会议与大臣一起讨论这个问题,最终一致认为成立网络专研小组,专门研究此问题
TCP/IP 家族的诞生
成立专家组之后,专家立即开始讨论如何使不同计算机建立通信,通过大量的考察不同的操作系统,专家们历经千辛万苦最终制定了统一标准——TCP/IP 协议族(注意:TCP/IP不是一个协议,而是一系列协议的总和),这个家族里包含了许多协议,比如常见的TCP协议,UDP协议
一次奇异的聊天
专家组把协议给国王看了看,国王非常高兴,马上派人把TCP/IP协议族中的所有协议分发给万千子民并给每一位子民拉了一根网线,子民们收到也非常高兴,各自研究其协议了
上官天宇和司马剑就是其中两位(下称上官和司马),数天后,在得知上官的地址(对应IP和端口)后,司马决定用可靠传输的TCP和上官进行通信,因为他不想在第一次聊条中漏掉任何文字
可是这个TCP有几个比较讨厌的就是聊天之前要做很多准备工作,有两步(真实的有三步,这里是为了体现两次握手的缺陷)
第一步: 他要发送一条建立连接的消息告诉对方咱两要通信了
第二步: 对方收到这个消息后,要回复他一个确认消息
上面两步(两次握手)做完了,两人才能够通信
于是,司马通过遵守TCP协议给上官天宇发了个”你好”,过了一会儿,他见上官没给他发确认消息
于是他就按照TCP的超时重传机制[简单的说就是在一定的时间后,如果对方没有回应,就认为这个消息发送失败,要重新发送],然后司马就重新发了一个消息给上官了
过了一小会,上官发来了确认消息,里面写着:“我收到了”(这个时候两次握手已经完成,两个人可以进行聊天了)
然后上官也给司马发了一个“你好”,相互聊了几句,就关闭了连接(四次挥手在下篇说)
殊不知过了一会,司马又收到聊了上官的确认消息,司马心中很纳闷,我没给他再发消息啊?喜欢探究原因的他把这个事情上报给TCP/IP的酋长了
设计上的缺陷
酋长带着问题来到了宫廷,见了专家组,专家组也很纳闷,想了许久,一个资深的元老突然说道,我们的设计可能有问题,现在我们的TCP是两次连接后就可以进行通信了,现在有这么一种情况,当A发送一个消息给B,这个消息由于网络的原因,阻塞在某个节点了,如下图
然后阻塞的时间很长,超出了咱们设定超时重发时间,那么A就会认为这个消息丢失了,然后重新发送
当A和B通信完成后,这个之前被A认为”失效的消息“到达了B,而对于B而言,以为这是一个新的请求连接消息,就向A发了一次确认(这就可以解释司马有收到了一次的确认消息了),而对于A而言,他认为他没有给B再次的发消息(因为上次的通话已经结束了),所以A不会理睬这条确认,但是B则会一直在傻傻的等待着A的消息
这就导致了B的时间被白白浪费(对于服务器而言,就是CPU等资源的一种浪费),这样是万万不可的,这就是为什么不能两次握手的原因
最终的修订
专家组的人一致赞同这个观点,然后几个人还做了几个实验,结论是确实是这个原因导致的,最后专家组坐在一块讨论如何修改这个TCP协议,元老发话了,其实修改也很简单,再加一次通信(握手)就行了,如下图
就是说A最后还要给B发一个确认,还是上次的那个例子,如果A不给B发第三次确认消息,那么B就认为A并没给他发消息,B也就不会在那里傻傻的等待了。最后酋长带着答案和修改草稿回到了部落。