知其然,知其所以然
网络协议原理 2026-10-15

TCP_NODELAY、TCP_CORK 与小包合并

实测 macOS 上 TCP_NODELAY 与 TCP_NOPUSH:读回值是内部标志(4 与 4096)而非 1;分两次 write 的消息 400 个段,拼接或 sendmsg 一次发只要 200 个;NOPUSH 开着 300 字节一个段都不发,拔塞后也不发,要再写 1 字节才以 301 字节一个段冲出。

网络协议 TCP TCP_NODELAY TCP_NOPUSH TCP_CORK sendmsg 小包合并 真实验证 动画演示
网络协议原理 2026-10-15

TCP keepalive:探测空闲连接是否还活着

实测 TCP keepalive:macOS 默认 2 小时才探测(最长 7800 秒才判死,公式);探测包是 0 字节、序号减 1 的纯 ACK;idle=2、intvl=1、cnt=3 的连接在 50% 丢包下最短 5.0 秒判死(ETIMEDOUT);对 example.com 的探测 3 个 3 个回应。

网络协议 TCP keepalive SO_KEEPALIVE TCP_KEEPALIVE 死连接检测 真实验证 动画演示
网络协议原理 2026-10-15

半开连接:对端消失时本端多久才知道

实测半开连接:进程被 kill -9 内核会发 FIN,本端立刻知道;SO_LINGER(1,0) 发 RST;在 50% 丢包下关闭 40 个连接,18 个客户端毫无察觉成为半开,发数据后 14 个收到 ECONNRESET;connect 到黑洞 75.0 秒后 ETIMEDOUT。

网络协议 TCP 半开连接 RST SO_LINGER keepalive 真实验证 动画演示
网络协议原理 2026-10-15

同时打开与自连接:两端同时 connect 会怎样

实测 TCP 同时打开与自连接:macOS 拒绝自连接(四种写法都是 EINVAL,线上 0 包);两个套接字互相 connect 在 150 ms 延迟下 SYN、SYN+ACK、ACK 各双向一个,中途都是 SYN_RCVD;向临时端口连 60000 次,4 次因源端口等于目标端口被 EINVAL 拒绝。

网络协议 TCP 同时打开 自连接 EINVAL SYN_RCVD 真实验证 动画演示
网络协议原理 2026-10-15

SO_REUSEADDR 与 SO_REUSEPORT:端口复用的两种含义

实测 macOS 上 SO_REUSEADDR 与 SO_REUSEPORT:REUSEADDR 绕过 TIME_WAIT 但不能让两个监听者共存;共存要两边都设 REUSEPORT;但 4 个监听者 400 个连接全部给了最后绑定的一个,UDP 也一样;多播要 REUSEADDR+REUSEPORT 或绑组地址才能多个套接字都收到。

网络协议 TCP UDP SO_REUSEADDR SO_REUSEPORT EADDRINUSE TIME_WAIT 真实验证 动画演示
网络协议原理 2026-10-15

TCP Fast Open:把数据塞进 SYN

实测 TCP Fast Open:macOS 上服务端 listen 后才能设选项、客户端用 connectx;cookie 与 SYN 带数据、50 ms 延迟下 202 ms 降到 101 ms、example.com 接受 SYN 里的请求;服务端密钥轮换后旧 cookie 被拒、数据不丢;客户端在 SYN 重传 3 次后对该目的地停用 TFO,停用只针对该目的地、至少 40 分钟没有恢复;Linux 容器对照:省一个往返、对不支持的服务端回退、SYN 数据可被重放、带数据的 SYN 被丢弃时每个连接多等约 1 秒。

网络协议 TCP TCP Fast Open TFO connectx SYN cookie 真实验证 动画演示
网络协议原理 2026-10-15

带宽时延积与套接字缓冲区:怎样把长肥管道填满

在 100 Mbit/s、RTT 100 ms 的 netlab 链路上扫描缓冲区:BDP 是 1,250,000 字节;接收窗口 256/512/1024 KiB 吞吐 2.53/4.98/9.91 MB/s,2048 KiB 起封顶 12.46 MB/s;过大的缓冲让 srtt 从 105 ms 涨到 197 ms;发送缓冲 64 KiB 只有 0.63 MB/s。

网络协议 TCP 带宽时延积 BDP SO_RCVBUF SO_SNDBUF bufferbloat 真实验证 动画演示
网络协议原理 2026-10-15

TCP 队头阻塞:一个包丢了,后面的数据都在等

实测 TCP 队头阻塞:单程 50 ms、丢包 3% 的链路上,UDP 的 p99 延迟 51.4 ms 但丢 3%;TCP 单连接 0 丢失但 28.8% 的消息延迟超过 80 ms,p99 229.8 ms;一次丢包通常拖住 9 条消息,并在同一时刻被一起释放;拆成 4 条连接降到 8.7%。

网络协议 TCP 队头阻塞 丢包 延迟 UDP 真实验证 动画演示
网络协议原理 2026-10-15

TCP 时间戳选项:RTT 测量与 PAWS

实测 TCP 时间戳选项:占 12 字节(lo0 载荷 16344−12=16332);时钟 1000 Hz;keepalive 探测不带时间戳;TSecr 配对 20/20 成功但抓包差值只是一半 RTT(50 对 100 ms);重传的 36 个段里 34 个 ACK 回显重传的 TSval,分得清是哪次发送;PAWS 只有计算。

网络协议 TCP 时间戳 TSval TSecr PAWS RTT Karn 真实验证 动画演示
网络协议原理 2026-10-15

丢包率对 TCP 吞吐的影响:用延迟与丢包注入实测

在 lo0 上用 netlab 注入延迟与丢包实测 TCP 吞吐:无丢包时往返 20 ms 为 193.57 MB/s、往返 100 ms 为 41.46 MB/s(窗口上限);5% 丢包让吞吐掉到基线的 2.2%;大多数格子实测与 Mathis 公式之比在 0.89~1.21;丢包率 ×4 吞吐约 ÷2.2~2.4。

网络协议 TCP 丢包 吞吐 Mathis公式 netlab 真实验证 动画演示
网络协议原理 2026-10-15

MSS 协商与钳制:隧道和 PPPoE 里的 MSS

实测 MSS 协商:SYN 里的 MSS = 接口 MTU − 40(lo0 16344、en0 1460);example.com 把 MSS 压到 1400,本机实际发出的最大段载荷 1388 = 1400 − 12;TCP_MAXSEG 在 connect/listen 前设置返回 EINVAL,连上后设置能把段限制在 1000 但不改握手;附各隧道应有 MSS 的计算表。

网络协议 TCP MSS MSS钳制 TCP_MAXSEG MTU 真实验证 动画演示
网络协议原理 2026-10-15

DNS 报文格式:头部、问题与资源记录,逐字节解析

逐字节解析 DNS 报文:29 字节查询(12 字节头 + 问题区);1.1.1.1 的 61 字节响应,记录名是指向偏移 12 的压缩指针 c0 0c;递归解析器标志 QR RD RA,权威服务器 QR AA 且无 RA,不托管的名字 REFUSED;名字压缩省 20%~41%;大小写原样回显,非法标签长度被丢弃。

网络协议 DNS 报文格式 名字压缩 RCODE AA RD RA 真实验证 动画演示
京ICP备2026067502号-1京公网安备11010502063487号