关于后端:详解三次握手和四次挥手

48次阅读

共计 2130 个字符,预计需要花费 6 分钟才能阅读完成。

申明:此文章仅是作者自学整顿的内容,并非通篇原创,因思否无奈设置转载多篇文章只能抉择原创,具体内容可见文末『参考文章』。文章援用模式不谨严,敬请见谅。

1. 三次握手

三次握手的过程和状态变迁

  1. 刚开始,Client(客户端,上面简称 C)和 Server(服务端,上面简称 S)都处于 CLOSED 状态。S 开启服务,处于监听状态,LISTEN
  2. C 收回第一个 SYN 报文,该报文不带数据,初始化了一个随机序列号(client_isn),标记 SYN 为 1。发送后,C 处于 SYN-SENT

  3. S 收到报文后,将 client_isn + 1 作为确认应答号,本人随机生成了一个序列号 server_isn,同时标记 SYN 和 ACK 为 1,传给 C 第二个报文,这个报文也不带数据。发送后,S 处于 SYN-RCVD

  4. C 收到第二个报文后,将 server_isn + 1 作为确认应答号,标记 ACK 为 1,传给 S 第三个报文,这个报文能够带应用层数据。发送后,C 处于 ESTABLISHED,S 收到后也处于 ESTABLISHED,单方能够替换数据了。

为什么握手三次而不是两次、四次?

  1. 阻止反复的历史连贯被初始化(次要起因)
    如下图所示👇,假如呈现旧的历史连贯(比方网络拥塞产生)先于新的连贯达到 S,S 基于旧的连贯产生 server_isn。在三次握手的状况下,C 能够通过上下文比拟判断这是一个历史连贯,返回 RST 报文通知 S 停止连贯。如果两次握手,旧连贯达到 S 后 S 返回报文,C 不进行第三次握手,就不足以产生足够的上下文判断这是否为历史连贯,不能防止历史连贯被初始化。
  2. 同步单方初始序列号
    C 和 S 依据序列号来确定发送的程序和完整性,所以同步序列号,保障牢靠十分重要。因而,C 收回的 client_isn 被 S 接管,S 必须返回一个 ACK,同理,S 收回的 server_isn 被 C 承受,C 也必须返回一个 ACK。但因为 第二次握手能够合并『确认 C 的序列号』和『发送 S 本身的序列号』两个动作,所以能够将 4 次略为 3 次。
  3. 防止资源节约
    和后面第 1 点提到的相似,如果遇到网络拥塞,C 收回的第一次握手没有被响应,就会触发超时重传,如果两次握手,那不仅重传的连贯会被 S 分配资源建设连贯,之前第 1 次收回的历史连贯也会被分配资源建设连贯,导致资源节约。

小结:

  • 不两次握手的起因:防止反复的历史连贯被初始化,防止重传的连贯导致资源节约,防止序列号不同步。(相似的了解:防止曾经生效的连贯申请被服务器接管,产生谬误。——谢希仁《计算机网络》
  • 不四次握手的起因:第二次握手将『确认应答客户端的序列号』和『发送服务器本身的序列号』两个动作合并,能够简化一步。是实践上起码的握手数,四次有冗余。

2. 四次挥手

四次挥手的过程和状态变迁

  1. 开始 C 和 S 两者都处于 ESTABLISHED 状态。C 想要停止连贯,发送了一个首部 FIN 标记为 1 的连贯,进入 FIN_WAIT_1 状态。
  2. S 收到报文后,发送一个 ACK 标记为 1 的报文,进入 CLOSED_WAIT 状态。
  3. C 收到应答报文后,进入 FIN_WAIT_2 状态。S 解决完残余的数据后,发送含 FIN 的报文,进入 LAST_ACK 状态。
  4. C 收到 FIN 报文后,返回一个 ACK 报文,进入 TIME_WAIT 状态。S 收到 ACK 报文后,敞开连贯进入 CLOSED 状态。
  5. C 期待 2MSL 后,敞开连贯进入 CLOSED 状态。

为什么挥手四次而不是三次?

C 发送 FIN 敞开连贯申请后,并非马上进入 CLOSED 状态,还在期待残余数据。

而此时 S 得悉 C 有敞开申请的用意后,发送完 ACK 报文,还得把残余的数据发送完,而后发送 FIN 通知 C 示意当初要敞开了。

所以,和三次握手不同,这里发送 S 发送 ACK 和发送 FIN 不能合并成一步。因为要等残余数据发送完。

为什么 TIME_WAIT 要等 2MSL?

什么是 MSL?
Max Segment Lifetime(最大报文生存工夫),和它相似的概念有 TTL(Time To Live),IP 协定头中的一个字段,示意报文能通过的最大路由数,每通过一个路由器减 1,当 TTL 为 0 时抛弃该数据报并发送 ICMP 报文给源主机。MSL 应该是大于等于使 TTL 为 0 所须要的工夫。

C 在收到 S 的 FIN 报文后从 FIN_WAIT_2 转 TIME_WAIT,发送进来的 ACK 如果没有被 S 接管到,那 S 会再发一次带 FIN 的报文。所以,S 重发 FIN 报文给 C 最多花 MSL,C 再发 ACK 给 S 最多 MSL,因而只需期待 2MSL。C 收到 FIN 后就开始计时,另外如果在 TIME_WAIT 中收到重传的 FIN 报文,2MSL 会被重置。

Linux 零碎中默认 2MSL 为 60 second。

为什么须要 TIME_WAIT 状态?

  1. 避免旧连贯的数据包被雷同端口的新连贯接管,产生数据错乱。
  2. 保障连贯正确敞开。就算 C 的 ACK 失落,S 也会重发 FIN。

TIME_WAIT 过多有什么危害?

个别是针对服务器发动的挥手。S 处于 TIME_WAIT。

此时,有两个问题:

  1. 内存资源占用。
  2. 端口占用。端口是无限资源,如果占用过多会无奈创立新连贯。

参考文章

  1. tcp 为什么要三次握手,而不能二次握手_简与美 -CSDN 博客_tcp 二次握手
  2. 能将三次握手了解到这个深度,面试官赞不绝口~
  3. 浏览器输出网址,小手一点,前面到底产生了什么?
  4. 硬不硬你说了算!近 40 张图解被问千百遍的 TCP 三次握手和四次挥手面试题
正文完
 0