网络知识大全
RFC 精读 · Transport · STD 7

RFC 9293

Transmission Control Protocol —— 2022 年把 RFC 793 及一串补丁收成现行 Internet Standard。首部、状态机、三次握手、四次关闭都在这里。

编号 / 标题
RFC 9293 · Transmission Control Protocol (TCP)
发布
August 2022
状态
Internet Standard · STD 7
Obsoletes
79387928736093642965286691
Updates
101111225961
原文
rfc-editor HTML · 纯文本 · datatracker
§3.1 Header Format

图 1:TCP 首部

       0                   1                   2                   3
       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |          Source Port          |       Destination Port        |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                        Sequence Number                        |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                    Acknowledgment Number                      |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |  Data |       |C|E|U|A|P|R|S|F|                               |
      | Offset| Rsrvd |W|C|R|C|S|S|Y|I|            Window             |
      |       |       |R|E|G|K|H|T|N|N|                               |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |           Checksum            |         Urgent Pointer        |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                           [Options]                           |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                                                               :
      :                             Data                              :
      :                                                               |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

             Note that one tick mark represents one bit position.

                        Figure 1: TCP Header Format

[……节选 Source Port / Destination Port]

   Sequence Number:  32 bits

     The sequence number of the first data octet in this segment (except
     when the SYN flag is set).  If SYN is set, the sequence number is
     the initial sequence number (ISN) and the first data octet is
     ISN+1.

   Acknowledgment Number:  32 bits

     If the ACK control bit is set, this field contains the value of the
     next sequence number the sender of the segment is expecting to
     receive.  Once a connection is established, this is always sent.

注解

无选项时 Data Offset=5,首部 20 字节。9293 把 CWR/ECE 画进主图(793 还没有),它们服务于 ECN,不是三次握手的角色。

序号按字节编号,不是按段。SYN 置位时 Seq=ISN,第一个数据字节是 ISN+1——也就是说 SYN 消耗一个序号。FIN 同样消耗一个。纯 ACK 不消耗序号,所以握手第三拍和紧随其后的数据可以共用同一个 Seq。

Ack 是累积确认:“我期望的下一个字节”。Ack=x 表示 x 之前都到了,不是“只确认了第 x 号”。

§3.3.2 State Machine Overview

十一个状态的官方定义

   A connection progresses through a series of states during its
   lifetime.  The states are: LISTEN, SYN-SENT, SYN-RECEIVED,
   ESTABLISHED, FIN-WAIT-1, FIN-WAIT-2, CLOSE-WAIT, CLOSING, LAST-ACK,
   TIME-WAIT, and the fictional state CLOSED.  CLOSED is fictional
   because it represents the state when there is no TCB, and therefore,
   no connection.  Briefly the meanings of the states are:

   LISTEN -  represents waiting for a connection request from any remote
      TCP peer and port.

   SYN-SENT -  represents waiting for a matching connection request
      after having sent a connection request.

   SYN-RECEIVED -  represents waiting for a confirming connection
      request acknowledgment after having both received and sent a
      connection request.

   ESTABLISHED -  represents an open connection, data received can be
      delivered to the user.  The normal state for the data transfer
      phase of the connection.

   FIN-WAIT-1 -  represents waiting for a connection termination request
      from the remote TCP peer, or an acknowledgment of the connection
      termination request previously sent.

   FIN-WAIT-2 -  represents waiting for a connection termination request
      from the remote TCP peer.

   CLOSE-WAIT -  represents waiting for a connection termination request
      from the local user.

   CLOSING -  represents waiting for a connection termination request
      acknowledgment from the remote TCP peer.

   LAST-ACK -  represents waiting for an acknowledgment of the
      connection termination request previously sent to the remote TCP
      peer (this termination request sent to the remote TCP peer already
      included an acknowledgment of the termination request sent from
      the remote TCP peer).

   TIME-WAIT -  represents waiting for enough time to pass to be sure
      the remote TCP peer received the acknowledgment of its connection
      termination request and to avoid new connections being impacted by
      delayed segments from previous connections.

   CLOSED -  represents no connection state at all.

注解

CLOSED 是“没有 TCB”,不是一个真能待着的房间。LISTEN 是被动打开(服务器 listen);SYN-SENT 是主动打开(客户端 connect)。

ESTABLISHED 才允许把数据交给用户。握手第三拍到达之前,即便 SYN 段里夹了数据,也要先缓冲。

TIME-WAIT 等的是 2MSL:既给最后那个 ACK 一次重传窗口,又让本四元组的迟到报文在网上死掉,以免污染下一个相同四元组的连接。

Figure 5

TCP 连接状态图

   NOTA BENE:  This diagram is only a summary and must not be taken as
      the total specification.  Many details are not included.

                               +---------+ ---------\      active OPEN
                               |  CLOSED |            \    -----------
                               +---------+<---------\   \   create TCB
                                 |     ^              \   \  snd SYN
                    passive OPEN |     |   CLOSE        \   \
                    ------------ |     | ----------       \   \
                     create TCB  |     | delete TCB         \   \
                                 V     |                      \   \
             rcv RST (note 1)  +---------+            CLOSE    |    \
          -------------------->|  LISTEN |          ---------- |     |
         /                     +---------+          delete TCB |     |
        /           rcv SYN      |     |     SEND              |     |
       /           -----------   |     |    -------            |     V
   +--------+      snd SYN,ACK  /       \   snd SYN          +--------+
   |        |<-----------------           ------------------>|        |
   |  SYN   |                    rcv SYN                     |  SYN   |
   |  RCVD  |<-----------------------------------------------|  SENT  |
   |        |                  snd SYN,ACK                   |        |
   |        |------------------           -------------------|        |
   +--------+   rcv ACK of SYN  \       /  rcv SYN,ACK       +--------+
      |         --------------   |     |   -----------
      |                x         |     |     snd ACK
      |                          V     V
      |  CLOSE                 +---------+
      | -------                |  ESTAB  |
      | snd FIN                +---------+
      |                 CLOSE    |     |    rcv FIN
      V                -------   |     |    -------
   +---------+         snd FIN  /       \   snd ACK         +---------+
   |  FIN    |<----------------          ------------------>|  CLOSE  |
   | WAIT-1  |------------------                            |   WAIT  |
   +---------+          rcv FIN  \                          +---------+
     | rcv ACK of FIN   -------   |                          CLOSE  |
     | --------------   snd ACK   |                         ------- |
     V        x                   V                         snd FIN V
   +---------+               +---------+                    +---------+
   |FINWAIT-2|               | CLOSING |                    | LAST-ACK|
   +---------+               +---------+                    +---------+
     |              rcv ACK of FIN |                 rcv ACK of FIN |
     |  rcv FIN     -------------- |    Timeout=2MSL -------------- |
     |  -------            x       V    ------------        x       V
      \ snd ACK              +---------+delete TCB          +---------+
        -------------------->|TIME-WAIT|------------------->| CLOSED  |
                             +---------+                    +---------+

                   Figure 5: TCP Connection State Diagram

注解 · 读图方法

左边一列是主动关闭路径:ESTAB → FIN-WAIT-1 → FIN-WAIT-2 → TIME-WAIT → CLOSED。右边是被动关闭:ESTAB → CLOSE-WAIT → LAST-ACK → CLOSED。中间 CLOSING 是双方同时 FIN。

原文 Note 2:若 FIN-WAIT-1 同时收到“对端 FIN + 对自己 FIN 的 ACK”,可直接进 TIME-WAIT(图上省略)。RST 可以从几乎任何状态跳出,图上也省略。

同一张图的手机可读版

颜色:墨框 = 过渡 · 青绿 = 可传数据 · 赤框 = 关闭尾声。与 Figure 5 对照,不是另一套规范。

打开
CLOSED无 TCB
LISTENpassive OPEN
SYN-SENTactive OPEN · snd SYN
SYN-RECEIVED已收 SYN,等 ACK
数据
ESTABLISHED数据可交付用户
关闭
FIN-WAIT-1主动方已发 FIN
FIN-WAIT-2FIN 已被确认
CLOSE-WAIT被动方已收 FIN
CLOSING同时关闭
LAST-ACK被动方等最后 ACK
TIME-WAIT通常主动关闭方;同步关闭双方都进
CLOSEDdelete TCB
Figure 6

基本三次握手

       TCP Peer A                                           TCP Peer B

   1.  CLOSED                                               LISTEN

   2.  SYN-SENT    --> <SEQ=100><CTL=SYN>               --> SYN-RECEIVED

   3.  ESTABLISHED <-- <SEQ=300><ACK=101><CTL=SYN,ACK>  <-- SYN-RECEIVED

   4.  ESTABLISHED --> <SEQ=101><ACK=301><CTL=ACK>       --> ESTABLISHED

   5.  ESTABLISHED --> <SEQ=101><ACK=301><CTL=ACK><DATA> --> ESTABLISHED

     Figure 6: Basic Three-Way Handshake for Connection Synchronization

[……节选逐行解说,下接 ACK 不占序号的原文]

   Note that the sequence number of the segment in line 5 is the same as
   in line 4 because the ACK does not occupy sequence number space (if
   it did, we would wind up ACKing ACKs!).

注解

A 选 ISN=100,B 选 ISN=300。B 的 ACK=101 确认的是那个 SYN(占了序号 100)。A 的 ACK=301 确认 B 的 SYN。第四、第五拍 Seq 都是 101:纯 ACK 不占号。

第三次握手本身是确认对端的 SYN(Figure 6 第 4 行的纯 ACK)。迟到的旧 SYN 走的是另一条路:对端回 SYN+ACK 后,本端用 RST 拆掉这条误建连接(Figure 8),不要把它说成“第三次握手就是发 RST”。

同时打开(Figure 7)是两边都从 CLOSED 发 SYN,各自走过 SYN-SENT → SYN-RECEIVED → ESTABLISHED。实现必须支持(MUST-10),抓包里少见。

Figure 12

正常关闭:四次

       TCP Peer A                                           TCP Peer B

   1.  ESTABLISHED                                          ESTABLISHED

   2.  (Close)
       FIN-WAIT-1  --> <SEQ=100><ACK=300><CTL=FIN,ACK>  --> CLOSE-WAIT

   3.  FIN-WAIT-2  <-- <SEQ=300><ACK=101><CTL=ACK>      <-- CLOSE-WAIT

   4.                                                       (Close)
       TIME-WAIT   <-- <SEQ=300><ACK=101><CTL=FIN,ACK>  <-- LAST-ACK

   5.  TIME-WAIT   --> <SEQ=101><ACK=301><CTL=ACK>      --> CLOSED

   6.  (2 MSL)
       CLOSED

                      Figure 12: Normal Close Sequence

注解

对端 FIN 必须被确认;本端 FIN 何时发取决于本方向关闭时机。两者语义独立,通常分开发,但本地应用已关闭时可同段 FIN+ACK(§3.6 Figure 12、§3.10.7.4)。

TIME-WAIT 通常是主动关闭方;同步关闭时双方均进入(§3.6 Figure 13)。被动单方关闭时,被动方从 LAST-ACK 直接 CLOSED。

线上看到三次,多半是本端在 ACK 对端 FIN 的同时已经可以发自己的 FIN,不是“挥手变成三次握手”。

抓包对照

实验室样本是三次握手。Wireshark 列 Seq / Ack / Win / Flags。相对序号默认从 0 起算,看 ISN 请关掉 Relative sequence numbers

tcp.srcport / tcp.dstport tcp.seq / tcp.ack tcp.flags.syn tcp.flags.ack tcp.flags.fin tcp.flags.reset tcp.window_size_value tcp.hdr_len Data Offset × 4 tcp.options.mss / sack / timestamp / wscale 握手三拍(相对序号): C→S SYN seq=0 S→C SYN, ACK seq=0 ack=1 C→S ACK seq=1 ack=1 tcpdump: 'tcp[tcpflags] & tcp-syn != 0' and tcp port 443

考点与易错点

  1. SYN、FIN 各消耗一个序号;纯 ACK 不消耗。握手第三拍可以带数据。
  2. Ack 是“下一个期望字节”,累积确认,不是“只确认这一段”。
  3. 两次握手不够:无法确认反向通路,也无法用 RST 拒绝迟到的旧 SYN。
  4. 四次挥手是因为全双工:收到 FIN 后仍可能继续发数据。
  5. TIME-WAIT 通常是主动关闭方;同步关闭时双方均进入。时长 2MSL,防最后 ACK 丢失和旧报文串连接。
  6. 实际发送窗口 = min(rwnd, cwnd)。窗口字段只通告 rwnd;拥塞窗口不在报文里。