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

DoT 与 DoH:加密 DNS 与它们的代价

实测 DoT 与 DoH:这台机器所在网络里 Cloudflare / Google / Quad9 / AdGuard 的加密 DNS 都连不上,只有阿里 223.5.5.5 可用;新建连接约 80 ms(UDP 的 7 倍),复用连接 8.6 ms;抓包看不到查询名但能看到 SNI;www.bbc.co.uk 经 DoT / DoH 拿到的仍是与明文同类的异常地址。

网络协议 DNS DoT DoH 加密 DNS TLS SNI 真实验证 动画演示
网络协议原理 2026-10-15

操作系统怎么解析名字:getaddrinfo、search 域、ndots 与 /etc/hosts

实测 macOS 怎么解析名字:按域名后缀在 7 个解析器里选(1 个单播、6 个 mDNS);AF_UNSPEC 也只发 A 查询(Request A records,没有 AAAA);单标签名字先加搜索域 lan 再问裸名字;localhost 不发 DNS;.local 走 224.0.0.251 的 mDNS,查不到要等 5002 ms。

网络协议 DNS getaddrinfo 存根解析器 搜索域 mDNS /etc/hosts 真实验证 动画演示
网络协议原理 2026-10-15

HTTP/1.1 报文:请求行、头部、空行与消息体

手工拆解 HTTP/1.1 报文:56 字节的请求、928 字节的响应(335 字节头部 + 4 + 589 字节分块消息体);头部大小写与 LF 行尾都被接受,缺 Host 得 400,未知方法 405,版本 HTTP/9.9 得 505;1.0 默认关连接、1.1 默认保持;单个头部上限在 130000~200000 字节之间。

网络协议 HTTP HTTP/1.1 报文格式 请求行 头部 chunked 真实验证 动画演示
网络协议原理 2026-10-15

HTTP/1.1 持久连接与流水线:连接复用与它的限制

实测 HTTP/1.1 的连接复用:RTT 100 ms 时 10 个资源每次新建 2024 ms、keep-alive 1114 ms、流水线 233 ms;但流水线有队头阻塞:快请求被慢请求拖到 702 ms(并行连接只要 202 ms),服务端不开 TCP_NODELAY 还会再晚 100 ms;example.com 支持流水线且空闲 130 秒也不关连接。

网络协议 HTTP HTTP/1.1 持久连接 keep-alive 流水线 队头阻塞 Nagle 真实验证 动画演示
网络协议原理 2026-10-15

分块传输编码与 Content-Length:消息体怎么划界

实测 HTTP 消息体怎么划界:example.com 的 589 字节分块响应只有 1 个 577 字节的块、框架开销 12 字节;100000 字节每块 100 字节开销 6.00% 而每块 16 KiB 只有 0.06%;chunked 让数据 0~1016 ms 陆续到达而 Content-Length 要等 1001 ms;缺长度的响应要等连接关闭才结束;长度写错、截断、错位各是什么后果。

网络协议 HTTP 分块传输 Transfer-Encoding Content-Length 请求走私 真实验证 动画演示
网络协议原理 2026-10-15

HTTP 方法的语义:安全性、幂等性与重试

实测 HTTP 方法语义:example.com 只开放 GET 与 HEAD(其它全部 405 且不带 Allow 头);HEAD 与 GET 的头部只差 Transfer-Encoding;响应丢失时 urllib3 自动重试 GET / PUT(服务器收到 3 次)而不重试 POST;强制重试 POST 会使服务器账上被重复执行 3 次。

网络协议 HTTP HTTP 方法 幂等性 安全方法 重试 POST 真实验证 动画演示
网络协议原理 2026-10-15

HTTP 缓存:Cache-Control、ETag 与条件请求

实测 HTTP 缓存:python.org 的 logo 新鲜期还剩 355388 秒;条件请求 304 比完整 200 少 97.8%(364 对 16384 字节);ETag 优先于日期;100 ms 往返下 10 次访问,无缓存头 500420 字节、max-age=60 只有 50069 字节、每次验证的 ETag 方案 50673 字节;附 Vary 缓存键的模拟。

网络协议 HTTP 缓存 Cache-Control ETag 条件请求 304 Vary 真实验证 动画演示
网络协议原理 2026-10-15

Range 请求与断点续传

实测 Range 请求:单段范围 206 且内容逐字节一致,起点超出得 416 并告知总大小,多段范围与未知单位被忽略返回 200;If-Range 在资源变了时回退到完整 200;中断后用 Range: bytes=6000- 续传,拼接后 SHA-256 一致;窗口受限的链路上 4 / 8 条连接并行下载比单连接快 3.5 / 6.3 倍。

网络协议 HTTP Range 206 416 If-Range 断点续传 并行下载 真实验证 动画演示
网络协议原理 2026-10-15

内容协商与压缩:Accept-Encoding 与 gzip / br

实测 HTTP 压缩:python.org CSS 349113 字节 gzip 后 125147(−64%),但不支持 br / zstd;example.com 的 br 334 < gzip 400 < 原文 577,并忽略 q=0;gzip -6 / brotli q5 / zstd -3 在本机的压缩率与耗时;已压缩数据再压几乎无收益;1 Mbit/s 链路上压缩让下载快 2.6~3 倍。

网络协议 HTTP 内容协商 Accept-Encoding gzip brotli zstd 压缩 真实验证 动画演示
网络协议原理 2026-10-15

Cookie:Set-Cookie 属性、作用域与 SameSite

拆开 baidu.com 的 4 个 Set-Cookie(max-age 2147483647 秒 ≈ 68 年);用 cookiejar 验证 8 个 Cookie 保存 5 个,域不匹配 / Max-Age=0 / 已过期的被丢弃,长路径的排在前面,Secure 不会走明文;example.com 对 64000 字节的 Cookie 头照收;附 SameSite 规则的模拟表。

网络协议 HTTP Cookie Set-Cookie SameSite Domain Path Secure 真实验证 动画演示
网络协议原理 2026-10-15

重定向:301 / 302 / 307 / 308 的区别

实测重定向:python.org 明文 301 到 https://www.python.org/;同一个 301 / 302,requests 把 POST 变 GET 而 urllib3 保持 POST + 请求体,307 / 308 才保证保持,urllib.request 对 307 / 308 直接抛异常;循环重定向 requests 31 次、urllib3 4 次、urllib.request 11 次后放弃;Location 的相对写法。

网络协议 HTTP 重定向 301 302 303 307 308 Location 真实验证 动画演示
网络协议原理 2026-10-15

HTTP 代理与 CONNECT 隧道

用自己写的最小代理实测 HTTP 代理:明文请求行变成绝对形式,代理能看到全部内容;HTTPS 走 CONNECT 隧道,代理只看得到 CONNECT 目标和 SNI、1751 / 6544 字节密文;客户端↔代理 100 ms 往返时 HTTPS 访问从 525 ms 增到 1161 ms(连到代理 101、CONNECT 264、TLS 362、HTTP 472 ms);403 / 502 / 407 的反应。

网络协议 HTTP 代理 CONNECT 隧道 SNI 407 真实验证 动画演示
京ICP备2026067502号-1京公网安备11010502063487号