三次握手灵魂三问

  1. 三次握手?
    前几天被问到一个问题:单向传输时延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。
  2. 等等,还没有结束~
    面试官还问了我三次握手到底节省了谁的资源?我。。
    在这里插入图片描述
    这个问题和为什么需要三次握手其实是一样的
    为了防止已失效的连接请求报文段又突然传送到B(过程1)
    如果没有过程3的话,服务器B会在发送完连接确认后就建立连接,但其实A的连接已经结束了呀,不会再有数据传过来了,这样服务器的连接资源不就浪费了嘛,所以应该是节省了服务器的资源。
  3. 秋豆麻袋,最后一问了,我发四
    面试官灵魂一问:那如果服务器的ACK(过程2)丢了怎么办?
    我当时是按超时重传答的,当然是答错啦,服务器B当时还没有建立连接啊喂!
    现在想想应该是A在一段时间后发现连接依然没有建立,重新发送连接请求吧。
    如果是A的ACK丢了,才会超时重传吧,因为A的连接在发送完ACK已经建立了。
    所以基础一定要扎实啊,不要像我一样一本正经的瞎说,现在想想真是太尴尬啦~
    ----------------------我是手动分割线------------------------------------
  4. 那我们来举一反三,看一下四次挥手吧
    上图为敬:(图是我盗的,感谢原作者,链接在这里:
    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收到确认,连接就真正的释放啦。

很开心这次面试真的让我查漏补缺了,至于结果就随缘吧~