🌀riba2534's Blog
凡事有交代,件件有着落,事事有回音
TCP三次握手、四次挥手复习

TCP三次握手、四次挥手

三次握手四次挥手知识点复习


  • TCP报文头

    • 格式:

      img

    • source port/destination port 分别代表源端口和目标端口

    • sequence/acknowledge number 用来标记发送和接收的字节数(序列号和ACK)

    • data offset 占 4 位,代表报文头中的字(32位)数,如果没有 options,则为固定值5

    • Flags,共 9 位

      • NS、CWR、ECE、URG,不懂
      • ACK,设置了后表示 acknowledge 字段生效
      • PSH,要求将缓存的数据推送给接收方
      • RST,重置连接,比如接收方已经关闭连接,收到迟到的报文,则会重置报文
      • SYN,三次握手第一次,代表同步 sequence number
      • FIN,四次挥手时的结束报文
    • Window size,拥塞控制中的窗口大小

    • Checksum,校验码,用于传输检测过程中的错误

    • Urgent pointer,不懂

    • Options,一般在三次握手、四次挥手中用到。不懂

  • 三次握手

    • 客户端随机生成一个序列号(sequence number),并发送SYN报文到服务端,请求连接

    • 服务端发送 SYN+ACK ,在应答请求的同时,也生成一个sequence id,请求同步

    • 客户端应答,服务端收到应答后双方建立连接

      img

    • 示意图

      img

    • 正如SYN标志的研一,三次握手的过程在建立连接的过程中完成了自身初始 sequence number同步。使用随机生成的 sequence number是为了防止网络中滞后的报文影响建立新的连接。

    • 为什么要进行三次握手,而不是两次?

      • 因为信道不可靠。考虑两次握手。假设客户端发送的第一个SYN在网络中滞留了,客户端因此重发SYN并建立连接,使用指导释放。此时滞留的第一个SYN终于到了,根据两次握手的规则,服务器直接进入 ESTABLISHED 状态,而此时客户端根本没有连接,不会理会服务端发送的报文,白白浪费了服务端的资源。
      • 事实上,只要信道不可靠,双方永远没有办法确认对方知道自己将要进入连接状态。例如三次握手,最后一次ACK如果丢失,则只有客户端进入连接状态。四次、五次多少次都有类似问题,三次是理论和实际的一个权衡。
  • 四次挥手

    断开连接需要四次挥手,可以有客户端也可以有服务器发起

    • \1. 发起方发送 FIN 报文,代表断开连接

    • \2. 接收方响应 ACK 报文,并在自己发送完未处理的报文后发送FIN报文

    • \3. 发起方接受ACK报文后等待接收方的FIN报文,收到后发送ACK报文,自己进入 TIME_WAIT 状态,等待 2MSL 后关闭连接

    • \4. 接收方收到ACK报文,关闭连接

    • 四次挥手示意图

      img

    • 为什么需要四次挥手?

      • 一般是因为连接是双向的, 每一方关闭连接时需要 FIN+ACK。因此一共四次。而从上图来看,主要是因为接收方发送ACK和发送FIN之间有间隔,接收方需要等待应用程序处理后发送FIN报文。如果ACK+FIN一起发送,则就变成三次挥手了。
    • 在做短连接做压测的时候经常会出现大量端口处理 TIME_WAIT 状态,导致无端口可用。为什么需要这个状态?

      • \1. 防止滞后的报文被后续建立的连接接收,因此结束先等待 2MSL 的时间。(MSL 是最大的报文存活时间,一来一回可以认为与上次连接相关的报文都不在网络中了)
      • \2. 确保接收方已经正确关闭连接,考虑发起方最后一次 ACK 滞留,则接收方一直处于 LAST_ACK 状态,而不会关闭连接。那么此时发送方重新建立连接 SYN,则由于序列号不同,处于 LAST_ACK 的接收方会响应 RST 报文。即连接未正确关闭导致后续连接无法建立。
  • 状态转换图:

    img


最后修改于 2020-04-27

知识共享许可协议
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。