第16章 TCP:传输控制协议

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

本章描述TCP协议的基本实现,包括TCP首部、TCP控制块、TCP状态机、TCP输入和输出的基本框架。


16.1 引言

TCP的特点

TCP(Transmission Control Protocol):

  • 传输控制协议
  • 面向连接
  • 可靠交付
  • 保证顺序
  • 流量控制
  • 拥塞控制
  • 全双工

TCP是可靠的面向连接的传输层协议。


TCP的复杂性

TCP为什么复杂:

  • 要保证可靠
  • 要处理拥塞
  • 要处理流量控制
  • 要处理各种异常情况
  • 状态很多
  • 定时器很多

TCP比UDP复杂得多。


本章讨论的内容

本章讨论的内容:

  • TCP首部格式
  • TCP控制块(tcpcb)
  • TCP状态机
  • TCP输入处理(tcp_input)
  • TCP输出处理(tcp_output)
  • TCP定时器概述

本章是TCP部分的概述。


16.2 TCP首部

TCP首部格式

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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|          源端口             |           目的端口            |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                         序号                                |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                         确认号                              |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|首部长度|  保留  |U|A|P|R|S|F|        窗口大小              |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|           检验和             |          紧急指针            |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                    选项(如果有)                          |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                    数据(如果有)                          |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

字段说明

字段大小说明
源端口16位发送方端口号
目的端口16位接收方端口号
序号32位本报文段数据的第一个字节的序号
确认号32位期望收到的下一个字节的序号
首部长度4位首部长度,以4字节为单位
保留6位保留,必须为0
URG1位紧急指针有效
ACK1位确认号有效
PSH1位推送操作
RST1位复位连接
SYN1位同步序号
FIN1位发送方完成发送
窗口大小16位接收窗口大小(流量控制)
检验和16位TCP首部+数据的检验和
紧急指针16位紧急数据的最后一个字节的偏移
选项可变可选,如MSS、窗口扩大、时间戳等

TCP首部最小20字节,选项最多40字节。


tcphdr结构

内核中的TCP首部结构:

struct tcphdr {
    u_short th_sport;           /* 源端口 */
    u_short th_dport;           /* 目的端口 */
    u_int   th_seq;             /* 序号 */
    u_int   th_ack;             /* 确认号 */
    u_char  th_x2:4;            /* 保留 */
    u_char  th_off:4;           /* 首部长度 */
    u_char  th_flags;           /* 标志位 */
    u_short th_win;             /* 窗口大小 */
    u_short th_sum;             /* 检验和 */
    u_short th_urp;             /* 紧急指针 */
};

对应TCP首部的C结构。


标志位

TCP标志位:

标志名称说明
URG紧急紧急指针有效
ACK确认确认号有效
PSH推送立即推送
RST复位复位连接
SYN同步同步序号,建立连接
FIN结束发送完成,关闭连接

每个标志位有不同的作用。


16.3 TCP控制块

tcpcb结构

TCP控制块(tcpcb):

struct tcpcb {
    struct  inpcb t_inpcb;      /* 通用PCB,必须是第一个 */
    
    /* 序号相关 */
    u_int   t_seq;              /* 发送下一个序号 */
    u_int   t_una;              /* 发送未确认的第一个序号 */
    u_int   t_rack;             /* 最近收到的ACK */
    u_int   t_rcv_nxt;          /* 接收下一个序号 */
    u_int   t_rcv_adv;          /* 接收窗口通告 */
    
    /* 窗口相关 */
    u_int   t_snd_wnd;          /* 发送窗口大小 */
    u_int   t_rcv_wnd;          /* 接收窗口大小 */
    u_int   t_snd_cwnd;         /* 拥塞窗口大小 */
    u_int   t_snd_ssthresh;     /* 慢启动阈值 */
    
    /* 状态 */
    int     t_state;            /* 连接状态 */
    int     t_flags;            /* 各种标志 */
    
    /* 定时器 */
    int     t_timer[TCPT_NTIMERS]; /* 定时器 */
    int     t_rxtcur;           /* 当前重传超时 */
    
    /* RTT测量 */
    int     t_srtt;             /* 平滑RTT */
    int     t_rttvar;           /* RTT方差 */
    int     t_rttseq;           /* RTT测量的序号 */
    int     t_rtt;              /* 当前RTT */
    
    /* 其他 */
    int     t_maxseg;           /* 最大段大小 */
    int     t_softerror;        /* 软错误 */
    /* ... 还有很多字段 ... */
};

关键字段说明

字段说明
t_inpcb通用inpcb,第一个成员,可以强制转换
t_seq下一个要发送的字节序号
t_una已发送但未确认的第一个字节的序号
t_rcv_nxt期望收到的下一个字节的序号
t_snd_wnd发送窗口(对端通告的)
t_rcv_wnd接收窗口(自己的)
t_snd_cwnd拥塞窗口(拥塞控制用)
t_snd_ssthresh慢启动阈值
t_state连接状态(CLOSED、ESTABLISHED等)
t_timer各种定时器
t_srtt / t_rttvarRTT估计值和方差
t_maxseg最大段大小(MSS)

tcpcb包含TCP连接的所有状态。


t_state状态

TCP连接状态:

状态说明
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双方同时关闭,等待ACK
LAST_ACK已发FIN+ACK,等待ACK
TIME_WAIT等待2MSL

TCP有11种状态。


16.4 TCP状态机

TCP状态转换图

TCP状态机:

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

这是简化的状态转换图。


状态转换说明

主要的状态转换:

  1. 主动打开

    • CLOSED → SYN_SENT → ESTABLISHED
  2. 被动打开

    • CLOSED → LISTEN → SYN_RCVD → ESTABLISHED
  3. 主动关闭

    • ESTABLISHED → FIN_WAIT_1 → FIN_WAIT_2 → TIME_WAIT → CLOSED
  4. 被动关闭

    • ESTABLISHED → CLOSE_WAIT → LAST_ACK → CLOSED
  5. 同时关闭

    • ESTABLISHED → FIN_WAIT_1 → CLOSING → TIME_WAIT → CLOSED

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


16.5 TCP输入处理

tcp_input函数

TCP输入处理(tcp_input):

  • IP层分用后调用
  • 处理收到的TCP段
  • 验证TCP首部
  • 查找对应的PCB
  • 根据状态处理
  • 可能发送应答
  • 可能更新状态

tcp_input是TCP输入的入口,很复杂。


输入处理的步骤

TCP输入处理的大致步骤:

  1. 验证

    • 验证长度
    • 验证校验和
  2. 查找PCB

    • 根据源目地址和端口查找
    • 找最匹配的
  3. 根据状态处理

    • LISTEN状态:处理连接请求
    • SYN_SENT状态:处理SYN+ACK
    • ESTABLISHED状态:处理数据和ACK
    • 等等
  4. 处理数据

    • 按序号排序
    • 放入接收缓冲区
    • 发送ACK
  5. 处理ACK

    • 确认发送的数据
    • 更新窗口
    • 可能触发重传定时器调整

tcp_input很复杂,要处理各种情况。


16.6 TCP输出处理

tcp_output函数

TCP输出处理(tcp_output):

  • 发送TCP段
  • 构造TCP首部
  • 计算校验和
  • 调用IP层发送
  • 启动重传定时器

tcp_output是TCP输出的入口。


什么时候调用tcp_output

调用tcp_output的时机:

  • 应用发送数据
  • 收到ACK需要发送新数据
  • 重传定时器超时
  • 坚持定时器超时
  • 需要发送ACK
  • 需要发送窗口更新
  • 等等

很多情况都会触发输出。


16.7 TCP定时器

TCP的定时器

TCP有多个定时器:

  1. 重传定时器(retransmission timer)

    • 发送数据后启动
    • 超时没收到ACK就重传
  2. 坚持定时器(persist timer)

    • 窗口为0时启动
    • 周期性探查窗口
  3. 保活定时器(keepalive timer)

    • 空闲连接的探查
    • 可选
  4. 2MSL定时器

    • TIME_WAIT状态
    • 等待2MSL后关闭

TCP有多个定时器,各有各的作用。


16.8 小结

TCP概述

  1. 特点

    • 面向连接
    • 可靠交付
    • 保证顺序
    • 流量控制
    • 拥塞控制
    • 全双工
  2. 复杂性

    • 状态多
    • 定时器多
    • 处理各种情况

TCP首部

  1. 格式

    • 源端口、目的端口
    • 序号、确认号
    • 首部长度、标志位
    • 窗口大小、检验和、紧急指针
    • 选项
  2. 标志位

    • URG、ACK、PSH、RST、SYN、FIN
  3. 长度

    • 最小20字节
    • 选项最多40字节

TCP控制块

  1. tcpcb结构

    • t_inpcb:通用PCB
    • 序号相关字段
    • 窗口相关字段
    • 状态
    • 定时器
    • RTT估计
    • 等等
  2. 状态

    • 11种状态
    • CLOSED到TIME_WAIT

TCP状态机

  1. 状态转换

    • 主动打开
    • 被动打开
    • 主动关闭
    • 被动关闭
    • 同时关闭
  2. TIME_WAIT

    • 等待2MSL
    • 确保最后一个ACK到达

TCP输入输出

  1. tcp_input

    • 输入入口
    • 验证、查找PCB
    • 按状态处理
    • 处理数据和ACK
  2. tcp_output

    • 输出入口
    • 构造段
    • 调用IP发送

TCP定时器

  1. 重传定时器

    • 超时重传
  2. 坚持定时器

    • 窗口探查
  3. 保活定时器

    • 空闲探查
  4. 2MSL定时器

    • TIME_WAIT

关键概念

  1. TCP

    • 可靠的面向连接协议
    • 复杂但强大
  2. tcpcb

    • TCP控制块
    • 包含所有状态
  3. 状态机

    • 11种状态
    • 各种转换
  4. tcp_input / tcp_output

    • 输入输出入口
    • 核心函数
  5. 定时器

    • 多个定时器
    • 各有用途

传输控制协议