JavaShuo
三次握手灵魂三问
时间 2021-01-08
标签
三次握手
四次挥手
面试
三次握手?
前几天被问到一个问题:单向传输时延50ms,建立连接、发送一个GET请求到接收到数据需要多长时间?
一开始我答的是三次握手的时间+一次请求一次响应=250ms,看面试官的反应好像不太对,让我画一下过程,我灵机一动回答200ms,勉强过关,结果二面又问了这个问题,尴尬。。
来看一下书上是怎么说的~
1:A向B发送连接请求,TCP规定SYN报文段(即SYN = 1的报文段)不能携带数据,但要消耗一个序号。
客户端进入SYN-SENT(同步已发送)状态。
2:B如果同意建立连接,则向A发送确认(ACK = 1),同样这个报文段不能携带数据。
服务器进入SYN-RCVD(同步收到)状态
3:客户端收到B的确认后,还要向B给出确认。
注意啦注意啦
ACK报文段可以携带数据,也就是说GET请求其实是可以在第三次传过去的。
如果ACK报文段没有携带数据是不消耗序号的
,也就是说下一个报文段的seq 依然= x+1。
这个时候TCP的连接已经建立,A进入已建立连接状态,B在接受到A的确认后也进入已建立连接状态。
说到这里答案就出来了,一开始我确实答错了,应该是A在发送完确认(也就是第三个步骤后)就已经建立连接,所以在100ms后就发送GET请求(也可以认为GET请求是随着第三次握手过去的),答案应该是4次传输,200ms。
等等,还没有结束~
面试官还问了我三次握手到底节省了谁的资源?我。。
这个问题和为什么需要三次握手其实是一样的
为了防止已失效的连接请求报文段又突然传送到B(过程1)
如果没有过程3的话,服务器B会在发送完连接确认后就建立连接,但其实A的连接已经结束了呀,不会再有数据传过来了,这样服务器的连接资源不就浪费了嘛,所以应该是节省了服务器的资源。
秋豆麻袋,最后一问了,我发四
面试官灵魂一问:那如果服务器的ACK(过程2)丢了怎么办?
我当时是按超时重传答的,
当然是答错啦,服务器B当时还没有建立连接啊喂!
现在想想应该是A在一段时间后发现连接依然没有建立,重新发送连接请求吧。
如果是A的ACK丢了,才会超时重传吧,因为A的连接在发送完ACK已经建立了。
所以基础一定要扎实啊,不要像我一样一本正经的瞎说,现在想想真是太尴尬啦~
----------------------我是手动分割线------------------------------------
那我们来举一反三,看一下四次挥手吧
上图为敬:(图是我盗的,感谢原作者,链接在这里:
https://blog.csdn.net/qq_38950316/article/details/81087809)
1:A先发出连接释放报文段,代表A以后没有数据再发了。FIN报文段即使不携带数据也要消耗一个序号。
2:B发送确认,告诉A我知道啦!A收到确认后就会关闭A到B方向的连接,这时TCP处于半关闭状态,就是A依然要接收来自B的数据。
A在FINAL_2状态接收数据、等待B的连接释放报文段。
3:B没有向A发送的数据了,就会发送释放报文。
4:A发确认后,
重点来咯
A会进入到TIME-WAIT状态,需要等待2MSL后,才能真的连接关闭。
为什么需要TIME_WAIT呢?
a. 如果过程4的ACK丢失,B会因为没收到确认而启动超时重传,有TIME_WAIT的阶段就可以保证A能收到这个重传的释放连接请求了。
b. 让本次连接产生的所有报文段在网络中消失,就不会出现在下一个连接中。
最后,B收到确认,连接就真正的释放啦。
很开心这次面试真的让我查漏补缺了,至于结果就随缘吧~