TCP头部

 

TCP头部字段详解

1. 源端口和目的端口(各16位)

  • 功能:标识发送和接收应用程序

  • 范围:0-65535(0-1023为知名端口)

  • 技术细节

    • 客户端通常使用临时端口(1024-65535)

    • 服务端使用固定端口(如HTTP=80, HTTPS=443)

    • 支持端口复用(SO_REUSEPORT选项)

// Linux内核端口选择算法 (net/ipv4/inet_connection_sock.c)
int inet_csk_get_port(struct sock *sk, unsigned short snum) {
    // ... 实现端口自动选择和冲突处理
}

2. 序列号(32位)

  • 功能:标识发送的数据字节流

  • 初始序列号(ISN):基于时钟的随机算法(RFC 6528)

    • 防止序列号预测攻击

    • 避免旧连接的报文干扰

  • 内核实现

    // Linux ISN生成算法 (net/ipv4/tcp_ipv4.c)
    u32 secure_tcp_seq(__be32 saddr, __be32 daddr,
                       __be16 sport, __be16 dport) {
        // 使用SipHash加密算法生成
    }
  • 回绕处理:当序列号达到2^32-1时回绕到0

3. 确认号(32位)

  • 功能:期望收到的下一个字节的序列号

  • 累积确认机制:确认号N表示所有小于N的字节已收到

  • 选择性确认(SACK):通过TCP选项实现非连续确认

4. 数据偏移(4位)

  • 功能:指定TCP头部长度(以4字节为单位)

  • 计算:头部长度 = 数据偏移 × 4

  • 范围:5(最小20字节)到15(最大60字节)

5. 保留位(4位)

  • 必须置0,为未来协议扩展保留

  • 实际使用中可能被实验性协议使用(需IANA批准)

6. 控制标志(9位)

标志位名称功能应用场景
URG紧急指针指示紧急数据处理Telnet中断命令
ACK确认确认号字段有效所有数据传输
PSH推送要求立即交付数据实时交互应用
RST重置立即终止连接端口扫描防御
SYN同步

标志组合示例

  • SYN+ACK:连接建立响应

  • FIN+ACK:正常连接终止

  • PSH+ACK:即时数据传输

7. 窗口大小(16位)

  • 功能:接收方通告的可用缓冲区大小

  • 流量控制机制:动态调整发送速率

  • 窗口缩放选项:通过选项扩展窗口大小(最高1GB)

    // Linux内核窗口缩放处理 (net/ipv4/tcp_input.c)
    void tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb) {
        // ... 处理窗口缩放选项
    }

  • 零窗口探测:当窗口为0时发送探测报文

8. 校验和(16位)


10. 选项字段(可变长度)

选项结构:
+--------+--------+--------+--------+
| Kind   | Length | Data...         |
+--------+--------+--------+--------+

核心选项详解:

  • 覆盖范围:TCP头部+数据+伪头部

  • 伪头部结构

    0      7 8     15 16    23 24    31
    +--------+--------+--------+--------+
    |          source address           |
    +--------+--------+--------+--------+
    |        destination address        |
    +--------+--------+--------+--------+
    |  zero  |  PTCL  |    TCP length   |
    +--------+--------+--------+--------+
  • 计算算法

    uint16_t tcp_checksum(const void *buff, size_t len, in_addr_t src_addr, in_addr_t dest_addr) {
        uint32_t sum = 0;
        const uint16_t *ptr = buff;
      
        // 伪头部计算
        struct pseudo_header psh = {src_addr, dest_addr, htons(IPPROTO_TCP), htons(len)};
        sum = calculate(&psh, sizeof(psh));
      
        // 数据计算
        while (len > 1) {
            sum += *ptr++;
            len -= 2;
        }
        if (len > 0) sum += (*ptr) & htons(0xFF00);
      
        // 折叠进位
        sum = (sum >> 16) + (sum & 0xFFFF);
        sum += (sum >> 16);
        return (uint16_t)(~sum);
    }

    9. 紧急指针(16位)

  • 功能:当URG=1时,指示紧急数据结束位置

  • 计算:紧急数据结束 = 序列号 + 紧急指针

  • 实际应用:SSH/Telnet的中断命令(Ctrl+C)

Kind名称长度功能
0选项结束1选项列表结束
1无操作1选项填充
2最大报文段4协商MSS(通常1460)
3窗口扩大因子3窗口缩放(2^14倍)
4选择性确认2启用SACK功能
5SACK块可变非连续接收的数据块
8时间戳10RTT测量和PAWS保护
28用户超时4连接超时设置
29认证可变TCP-AO安全认证

超时重传为例,假设客户端(Client)向服务器(Server)发送数据包,但未收到ACK确认。

    场景步骤:

    Client发送数据包(初始传输)

    • TCP头部包含选项字段(如时间戳):
      数据偏移 = 8(头部总长32字节 = 8 × 4)
      选项字段:时间戳(Timestamp)值 = T1
      序列号(Seq) = 100
      数据 = "Hello"
      
    • 数据包结构:
      | 20字节固定头部 | 12字节选项(时间戳) | 数据 "Hello" |
      

    Server未收到该包(可能因网络拥塞丢失):

    • Client在重传超时(RTO) 后未收到ACK,触发重传。

    Client重传数据包

    数据偏移 = 8(长度不变)
    选项字段:时间戳值 = T2(T2 > T1)
    序列号(Seq)仍为 100(相同数据)
    数据 = "Hello"(不变)
    

    关键点分析:

    • 选项长度一致性:重传时数据偏移值仍为8,表明头部长度未变(选项字段仍存在)。
    • 选项内容变化:时间戳更新(T1 → T2),帮助计算RTT(往返时间)和重传延迟。
    • 接收方处理:Server通过数据偏移=8跳过32字节头部,直接解析数据"Hello"。
    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包
    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

    余额充值