TCP-IP详解卷3 第12章:T/TCP实现——TCP用户请求

来源:《TCP/IP详解卷3:TCP事务协议、HTTP、NNTP和UNIX域协议》第12章(W. Richard Stevens)。pdf-inspector 报 no readable pages(该系列已知问题),pdftotext 兜底提取成功,约 11 页。

本章范围

tcp_usrreq 中被 T/TCP 修改的三个请求:PRU_CONNECT、PRU_SEND、PRU_SEND_EOF;外加新函数 tcp_connect、修改的 tcp_usrclosed、新增的 tcp_sysctl。tcp_ctloutput(TCP_NOPUSH/TCP_NOOPT 插口选项)修改太琐碎不讲。

PRU_CONNECT 的关键事实

  • 即使两端都支持 T/TCP,显式 connect() 仍走完整三次握手——因为 connect 无法携带数据,tcp_output 只发 SYN。
  • 要跳过三次握手,应用必须放弃 connect,改用 sendto/sendmsg 带对端地址(隐式连接建立)。这是 T/TCP 性能收益的使用前提。

tcp_connect 十步流程(新函数,显式+隐式共用)

  1. in_pcbbind 绑本地端口;
  2. in_pcbladdr 定本地地址 + in_pcblockup 查 PCB(T/TCP 下客户端常为一系列事务复用同一本地端口,撞上已有 PCB 的概率更高);
  3. TIME_WAIT 截断三条件:①PCB 处于 TIME_WAIT ②连接持续 < MSL ③原连接用过 T/TCP(收到过 CC/CCnew)——三者全真则 tcp_close 截断旧连接; 4-6. 补全插口对、tcp_template 缓存 IP+TCP 首部、算窗口宽度因子;
  4. soisconnecting 置 SYN_SENT,连接建立定时器 75 秒;
  5. ISS 初始化(TCP_ISSINCR 随机化宏);
  6. CC 值生成:读对端 TAO 缓存;全局 tcp_ccgen += CC_INC(无论是否用 CC 选项,每建一连接 +1);
  7. CC vs CCnew 判定:tao_ccsent 非 0 且 cc_send ≥ tao_ccsent → 发 CC 并更新 TAO 缓存;否则发 CCnew 且 tao_ccsent 置 0。
    • 原因:CC 回绕(如上次发 1、本次 2147483648)时对方无法区分新 SYN 与过时重复报文,必须 CCnew 强制三次握手并触发对方缓存更新。
    • 经典缺陷(Olah 1995):Braden 参考实现把 CC/CCnew 判定放在 tcp_output 发包时而非主动打开时——SYN 丢失重传换值后,过时重复 CC 报文可能被服务器误收。正确做法:判定必须在客户端主动打开时刻一次性完成。

PRU_SEND / PRU_SEND_EOF(隐式打开路径)

  • nam 非空 + 连接状态 CLOSED/LISTEN → tcp_connect 隐式建连;初始发送窗直接设 4096(TTCP_CLIENT_SND_WND,T/TCP 允许在收到服务器窗口通告前就发数据)。
  • MSS:tcp_mssrcvd 第二参传 -1(尚未收 SYN),用 TAO 缓存 tao_mssopt 或路由表 rmx_mtu 预置 t_maxseg/t_maxopd——收到 SYN 之前 TCP 控制块里就必须有 MSS 值;之后真收到带 MSS 选项的 SYN 时 tcp_dooptions 再校正。
  • MSG_EOF → sosend 产生 PRU_SEND_EOF → 置 SS_CANTSENDMORE → tcp_usrclosed 把 SYN_SENT 变迁到 SYN_SENT*(加星隐藏状态,设 TF_SENDFIN)。
  • 效果:sendto(MSG_EOF) 首发报文段同时含 SYN + 数据 + FIN——1.5 轮 RTT 短事务的源码基础。

tcp_usrclosed 与 tcp_sysctl

  • tcp_usrclosed 唯一修改:允许进程关闭尚处于 SYN_SENT / SYN_RCVD 状态的连接(设 TF_SENDFIN 进入对应加星状态)。
  • tcp_sysctl:以 net.inet.tcp 前缀访问,挂在 proto_sw 的 pr_sysctl 字段。非 T/TCP 必需,但提供了不调调试器改内核 TCP 变量的简便通道——sysctl 网络调参机制的早期落地,现仅支持 3 个变量。

历史判断(12.7 节,1994 年视角)

作者类比 RFC 1323(窗口缩放/时间戳)扩散路径:1992.5 Skibo Net/2 修改 → 1993.4 Braden/Wei SunOS 4.1.1 版 → 1993.8 并入 4.4BSD → 1994.4 4.4BSD-Lite 公开 → 1995 厂商跟进;但 PC 平台普及差(实测 <2% 客户端带 1323 选项)。预测 T/TCP 走类似路:SunOS 4.1.3 参考实现(1994.9)受众窄,FreeBSD 移植(1995 初)才是传播载体。T/TCP 与实现互通安全:仅两端都支持 CC 选项时启用。 (后见之明:T/TCP 最终未获广泛部署,CCnew 回绕、TAO 缓存状态、中间盒干扰是主因之一;其”用令牌替代握手”思想在 TCP Fast Open (RFC 7413, 2014) 中复活。)

可行动点

  • 想吃到 SYN 数据携带类优化(TFO 同理),应用层必须用 sendto/带地址的 sendmsg + MSG_EOF/MSG_FASTOPEN 语义,connect 路径拿不到收益。
  • 任何”用递增令牌跳过握手”的设计都要回答:令牌回绕怎么办(CCnew 思路)、令牌判定放哪个时点(主动打开时,不能放重传路径)、旧令牌重复包如何拒收。

关联