第22章 TCP:连接的建立与终止

所属:TCP/IP详解 卷2:实现 来源:TCP/IP详解 卷2:实现

本章描述TCP连接的建立与终止的实现,包括三次握手、四次挥手、TCP状态机和复位报文等。


22.1 引言

连接的建立和终止

TCP是面向连接的协议:

  • 传输数据前要先建立连接
  • 传输完要终止连接
  • 连接的建立和终止都有规定的过程

连接管理是TCP的基本功能。


本章讨论的内容

本章讨论的内容:

  • 连接建立(三次握手)
  • 连接终止(四次挥手)
  • TCP状态机
  • 复位报文(RST)
  • 同时打开和同时关闭
  • 半关闭

本章讨论连接的建立和终止。


22.2 连接建立:三次握手

为什么需要三次握手

为什么需要三次握手:

  1. 同步序号

    • 双方都要知道对方的初始序号
    • 双方都要确认对方的序号
  2. 确认双方都有收发能力

    • 客户端能发能收
    • 服务端能发能收
  3. 防止旧的连接请求

    • 防止迟到的连接请求
    • 建立错误的连接

三次握手确保连接可靠建立。


三次握手的过程

三次握手(Three-Way Handshake):

客户端                            服务端
   |                                |
   | ------ SYN ------->            |  1. 客户端发SYN
   |     seq=x                      |
   |                                |
   | <--- SYN+ACK ----              |  2. 服务端回SYN+ACK
   |     seq=y, ack=x+1             |
   |                                |
   | ------ ACK ------->            |  3. 客户端回ACK
   |     seq=x+1, ack=y+1           |
   |                                |
   +------ 连接建立 ------+         |

三个报文:

  1. SYN:客户端→服务端,请求连接
  2. SYN+ACK:服务端→客户端,同意连接,同步自己的序号
  3. ACK:客户端→服务端,确认服务端的序号

三次握手建立连接。


初始序号(ISN)

初始序号(Initial Sequence Number, ISN):

  • 建立连接时的起始序号
  • 不是从0开始
  • 随机生成
  • 随时间增长

为什么随机:

  • 防止序号猜测攻击
  • 防止旧的分组混淆

ISN是随机的,不是0。


MSS选项

MSS选项(Maximum Segment Size):

  • 连接建立时协商
  • 告诉对方自己最大能接收的段大小
  • 通常是MTU - IP首部 - TCP首部
  • 以太网通常是1460字节

为什么需要协商:

  • 避免分片
  • 提高效率
  • 双方知道对方的MSS

MSS在连接建立时协商。


22.3 连接终止:四次挥手

为什么需要四次挥手

为什么需要四次挥手:

  • TCP是全双工的
  • 两个方向都要关闭
  • 每个方向单独关闭
  • 所以需要四次

全双工,两个方向都要关闭。


四次挥手的过程

四次挥手(Four-Way Handshake):

客户端                            服务端
   |                                |
   | ------ FIN ------->            |  1. 客户端发FIN,关闭客户端→服务端方向
   |     seq=u                      |
   |                                |
   | <----- ACK -------             |  2. 服务端回ACK
   |     seq=v, ack=u+1             |
   |                                |
   | <----- FIN -------             |  3. 服务端发FIN,关闭服务端→客户端方向
   |     seq=w                      |
   |                                |
   | ------ ACK ------->            |  4. 客户端回ACK
   |     seq=u+1, ack=w+1           |
   |                                |
   +------ 连接终止 ------+         |

四个报文:

  1. FIN:主动关闭方发,关闭自己这个方向
  2. ACK:被动关闭方回,确认FIN
  3. FIN:被动关闭方发,关闭自己这个方向
  4. ACK:主动关闭方回,确认FIN

四次挥手终止连接。


半关闭

半关闭(Half-Close):

  • 一个方向关闭了,另一个方向还开着
  • 客户端发了FIN,服务端还能发数据
  • 服务端发了FIN,客户端还能发数据

为什么需要:

  • 客户端发完数据了,发FIN
  • 服务端还有数据要发
  • 可以继续发,发完再发FIN

半关闭允许单向关闭。


22.4 TCP状态机

11种状态

TCP的11种状态:

状态说明
CLOSED关闭,没有连接
LISTEN监听,等待连接请求
SYN_SENT已发SYN,等待SYN+ACK
SYN_RCVD已收SYN,已发SYN+ACK,等待ACK
ESTABLISHED已建立连接,可以传输数据
FIN_WAIT_1已发FIN,等待ACK
FIN_WAIT_2已收FIN的ACK,等待对端FIN
CLOSE_WAIT已收FIN,等待应用关闭
CLOSING双方同时发FIN,等待ACK
LAST_ACK已发FIN+ACK,等待ACK
TIME_WAIT等待2MSL

TCP有11种状态。


状态转换图

TCP状态转换图(简化):

                        +--------+
                        | CLOSED |
                        +--------+
                          |    ^
              passive open |    | close
                          v    |
                        +--------+
                 send   | LISTEN | recv
                 SYN    +--------+ SYN
                          |    ^
                          v    |
                     +-----------+  recv
               send  | SYN_SENT  |  SYN+ACK
               SYN   +-----------+  send
                          |    |  ACK
                          v    |
                     +-----------+
               recv  | SYN_RCVD  |  send
               ACK   +-----------+  ACK
                          |
                          v
                     +-----------+
                     |ESTABLISHED|
                     +-----------+
                       |       |
            active close|       |passive close
               send FIN |       |recv FIN
                       v       v
                +-----------+ +-----------+
                |FIN_WAIT_1 | |CLOSE_WAIT |
                +-----------+ +-----------+
                  |       |        |
          recv    |       |recv    |close
          ACK     |       |FIN     |send FIN
                  v       v        v
           +-----------+ +-----------+
           |FIN_WAIT_2 | | CLOSING   |
           +-----------+ +-----------+
                  |           |
            recv  |      recv |
            FIN   |      ACK  |
                  v           v
           +-----------+ +-----------+
           | TIME_WAIT | | LAST_ACK  |
           +-----------+ +-----------+
                  |           |
            2MSL  |      recv |
            超时  |      ACK  |
                  v           v
                +--------+
                | CLOSED |
                +--------+

这是简化的状态转换图。


常见的状态转换路径

主动打开+主动关闭:

CLOSED → SYN_SENT → ESTABLISHED → FIN_WAIT_1 → FIN_WAIT_2 → TIME_WAIT → CLOSED

被动打开+被动关闭:

CLOSED → LISTEN → SYN_RCVD → ESTABLISHED → CLOSE_WAIT → LAST_ACK → CLOSED

同时关闭:

ESTABLISHED → FIN_WAIT_1 → CLOSING → TIME_WAIT → CLOSED

不同的情况有不同的路径。


22.5 TIME_WAIT状态

为什么需要TIME_WAIT

TIME_WAIT状态:

  • 主动关闭的最后状态
  • 等待2MSL(Maximum Segment Lifetime)
  • 然后才到CLOSED

为什么需要:

  1. 确保最后一个ACK到达

    • 最后一个ACK可能丢
    • 对端会重发FIN
    • TIME_WAIT时还能重发ACK
    • 不然对端一直重传
  2. 让旧的分组消失

    • 防止旧连接的分组
    • 被新连接当成新的
    • 等2MSL,旧的都没了

两个原因:可靠关闭和防止混淆。


2MSL等待时间

2MSL等待时间:

  • MSL:最大分节生命期
  • 分组在网络中最长存活时间
  • RFC建议2分钟
  • 实际常用30秒到2分钟
  • 2MSL就是1分钟到4分钟

为什么是2MSL:

  • 一个方向最多MSL
  • 另一个方向最多MSL
  • 加起来2MSL
  • 确保所有旧分组都消失

2MSL确保旧分组都消失。


TIME_WAIT的影响

TIME_WAIT的影响:

  • 占用资源
  • 短连接频繁的话,很多TIME_WAIT
  • 可能耗尽端口

怎么处理:

  • 正常现象,不用太担心
  • 调整参数(如net.ipv4.tcp_tw_reuse)
  • 长连接减少TIME_WAIT

TIME_WAIT是正常的,是TCP可靠性的保证。


22.6 复位报文(RST)

什么是复位报文

复位报文(Reset, RST):

  • TCP的一种报文
  • RST标志位为1
  • 用于复位连接
  • 表示错误或异常情况

RST用于异常情况。


什么时候发RST

发送RST的情况:

  1. 连接不存在

    • 收到SYN,但没有监听的端口
    • 发RST拒绝
  2. 连接异常

    • 收到的报文不属于任何连接
    • 发RST
  3. 异常关闭

    • 应用异常关闭
    • 发RST而不是FIN
  4. 半开连接

    • 一端已经关了,另一端不知道
    • 收到报文发RST

各种异常情况都可能发RST。


RST和FIN的区别

RST和FIN的区别:

对比项FINRST
含义正常关闭异常复位
过程四次挥手直接复位
数据缓冲区的数据会尽量发直接丢弃
状态TIME_WAIT等直接CLOSED
用途正常关闭异常情况

FIN是正常关闭,RST是异常复位。


22.7 同时打开和同时关闭

同时打开

同时打开(Simultaneous Open):

  • 双方同时发SYN
  • 双方同时收到SYN
  • 双方都发SYN+ACK
  • 然后都收到SYN+ACK
  • 连接建立

状态转换:

CLOSED → SYN_SENT → SYN_RCVD → ESTABLISHED

报文交换:

  • 4个报文(两个SYN,两个SYN+ACK)
  • 正常是3个

同时打开比较少见。


同时关闭

同时关闭(Simultaneous Close):

  • 双方同时发FIN
  • 双方同时收到FIN
  • 双方都发ACK
  • 然后都收到ACK
  • 都进入TIME_WAIT

状态转换:

ESTABLISHED → FIN_WAIT_1 → CLOSING → TIME_WAIT → CLOSED

报文交换:

  • 4个报文(两个FIN,两个ACK)
  • 和正常的数量一样,只是顺序不同

同时关闭也比较少见。


22.8 小结

连接建立

  1. 三次握手

    • SYN → SYN+ACK → ACK
    • 同步序号
    • 确认双方能力
  2. 初始序号

    • 随机生成
    • 不是0
    • 防止攻击和混淆
  3. MSS选项

    • 协商最大段大小
    • 避免分片

连接终止

  1. 四次挥手

    • FIN → ACK → FIN → ACK
    • 全双工,两个方向都关
  2. 半关闭

    • 一个方向关了,另一个还开着
    • 可以继续发数据

TCP状态机

  1. 11种状态

    • CLOSED、LISTEN、SYN_SENT、SYN_RCVD
    • ESTABLISHED
    • FIN_WAIT_1、FIN_WAIT_2、CLOSE_WAIT
    • CLOSING、LAST_ACK、TIME_WAIT
  2. 状态转换

    • 主动打开
    • 被动打开
    • 主动关闭
    • 被动关闭
    • 同时打开/关闭

TIME_WAIT

  1. 为什么需要

    • 确保最后ACK到达
    • 让旧分组消失
  2. 2MSL

    • 最大分节生命期
    • 等待2倍MSL
  3. 影响

    • 占用资源
    • 正常现象

复位报文

  1. 什么是RST

    • 复位报文
    • 异常情况用
  2. 什么时候发

    • 连接不存在
    • 连接异常
    • 异常关闭
  3. 和FIN的区别

    • FIN是正常关闭
    • RST是异常复位

同时打开和关闭

  1. 同时打开

    • 双方同时发SYN
    • 4个报文
    • 少见
  2. 同时关闭

    • 双方同时发FIN
    • 4个报文
    • 少见

关键概念

  1. 三次握手

    • 建立连接
    • 同步序号
  2. 四次挥手

    • 关闭连接
    • 全双工
  3. 状态机

    • 11种状态
    • 各种转换
  4. TIME_WAIT

    • 2MSL等待
    • 两个原因
  5. RST

    • 复位
    • 异常情况

三次握手