diff --git a/notes/pics/dhcp.png b/notes/pics/dhcp.png new file mode 100644 index 00000000..08932a44 Binary files /dev/null and b/notes/pics/dhcp.png differ diff --git a/notes/pics/dns-resolve.png b/notes/pics/dns-resolve.png new file mode 100644 index 00000000..89ffbfbd Binary files /dev/null and b/notes/pics/dns-resolve.png differ diff --git a/notes/pics/email-flow.png b/notes/pics/email-flow.png new file mode 100644 index 00000000..f2b88cd1 Binary files /dev/null and b/notes/pics/email-flow.png differ diff --git a/notes/pics/ftp-modes.png b/notes/pics/ftp-modes.png new file mode 100644 index 00000000..430e19c2 Binary files /dev/null and b/notes/pics/ftp-modes.png differ diff --git a/notes/pics/mime.png b/notes/pics/mime.png new file mode 100644 index 00000000..14b2e465 Binary files /dev/null and b/notes/pics/mime.png differ diff --git a/notes/pics/url-timeline.png b/notes/pics/url-timeline.png new file mode 100644 index 00000000..56a91a5d Binary files /dev/null and b/notes/pics/url-timeline.png differ diff --git a/notes/计算机网络 - 应用层.md b/notes/计算机网络 - 应用层.md index f23c4279..597df19a 100644 --- a/notes/计算机网络 - 应用层.md +++ b/notes/计算机网络 - 应用层.md @@ -15,6 +15,7 @@ * [2. ARP 解析 MAC 地址](#2-arp-解析-mac-地址) * [3. DNS 解析域名](#3-dns-解析域名) * [4. HTTP 请求页面](#4-http-请求页面) + * [参考资料](#参考资料) @@ -24,7 +25,11 @@ DNS 是一个分布式数据库,提供了主机名和 IP 地址之间相互转 域名具有层次结构,从上到下依次为:根域名、顶级域名、二级域名。 -

+以解析 www.example.com 为例:主机先查浏览器缓存、操作系统缓存和 hosts 文件,没有命中就向本地 DNS 服务器查询。本地 DNS 服务器依次询问根服务器、com 顶级域服务器和 example.com 的权威服务器,前两者只返回下一级服务器的地址,权威服务器返回最终的 IP 地址。 + +

+ +主机到本地 DNS 服务器是递归查询,主机只等最终结果;本地 DNS 服务器到其它服务器是迭代查询,由它自己一步步问下去。每一级的结果都按 TTL 缓存,所以大多数查询在本地 DNS 服务器甚至主机上就能得到结果。 DNS 可以使用 UDP 或者 TCP 进行传输,使用的端口号都为 53。大多数情况下 DNS 使用 UDP 进行传输,这就要求域名解析器和域名服务器都必须自己处理超时和重传从而保证可靠性。在两种情况下会使用 TCP 进行传输: @@ -42,11 +47,9 @@ FTP 使用 TCP 进行连接,它需要两个连接来传送一个文件: - 主动模式:服务器端主动建立数据连接,其中服务器端的端口号为 20,客户端的端口号随机,但是必须大于 1024,因为 0\~1023 是熟知端口号。 -

- - 被动模式:客户端主动建立数据连接,其中客户端的端口号由客户端自己指定,服务器端的端口号随机。 -

+

主动模式要求客户端开放端口号给服务器端,需要去配置客户端的防火墙。被动模式只需要服务器端开放端口号即可,无需客户端配置防火墙。但是被动模式会导致服务器端的安全性减弱,因为开放了过多的端口号。 @@ -63,7 +66,7 @@ DHCP 工作过程如下: 3. 如果客户端选择了某个 DHCP 服务器提供的信息,那么就发送 Request 报文给该 DHCP 服务器。 4. DHCP 服务器发送 Ack 报文,表示客户端此时可以使用提供给它的信息。 -

+

## 远程登录协议 @@ -77,13 +80,13 @@ TELNET 可以适应许多计算机和操作系统的差异,例如不同操作 邮件协议包含发送协议和读取协议,发送协议常用 SMTP,读取协议常用 POP3 和 IMAP。 -

+

### 1. SMTP SMTP 只能发送 ASCII 码,而互联网邮件扩充 MIME 可以发送二进制文件。MIME 并没有改动或者取代 SMTP,而是增加邮件主体的结构,定义了非 ASCII 码的编码规则。 -

+

### 2. POP3 @@ -101,14 +104,31 @@ IMAP 协议中客户端和服务器上的邮件保持同步,如果不手动删 | 动态主机配置协议 | DHCP | 67/68 | UDP | | | 简单网络管理协议 | SNMP | 161/162 | UDP | | | 文件传送协议 | FTP | 20/21 | TCP | 控制连接 21,数据连接 20 | +| 安全外壳协议 | SSH | 22 | TCP | | | 远程终端协议 | TELNET | 23 | TCP | | | 超文本传送协议 | HTTP | 80 | TCP | | +| 超文本传送安全协议 | HTTPS | 443 | TCP | HTTP/3 使用 UDP | | 简单邮件传送协议 | SMTP | 25 | TCP | | | 邮件读取协议 | POP3 | 110 | TCP | | | 网际报文存取协议 | IMAP | 143 | TCP | | ## Web 页面请求过程 +在浏览器中输入 https://www.example.com/ 并回车后,主要经过以下步骤: + +1. 浏览器解析 URL,检查缓存,有未过期的缓存时直接使用; +2. DNS 解析域名,得到 IP 地址; +3. 与服务器进行 TCP 三次握手,HTTPS 还要进行 TLS 握手; +4. 发送 HTTP 请求,服务器处理后返回响应; +5. 浏览器解析 HTML,再请求其中引用的 CSS、JavaScript、图片等资源,最后渲染出页面; +6. 连接保持一段时间供后续请求复用,空闲后关闭。 + +以下是本机访问该网址时各阶段的耗时: + +

+ +下面从网络各层的角度,看一台刚接入网络的主机发出这个请求的完整过程。 + ### 1. DHCP 配置主机信息 - 假设主机最开始没有 IP 地址以及其它信息,那么就需要先使用 DHCP 来获取。 @@ -166,3 +186,8 @@ IMAP 协议中客户端和服务器上的邮件保持同步,如果不手动删 - HTTP 服务器从 TCP 套接字读取 HTTP GET 报文,生成一个 HTTP 响应报文,将 Web 页面内容放入报文主体中,发回给主机。 - 浏览器收到 HTTP 响应报文后,抽取出 Web 页面内容,之后进行渲染,显示 Web 页面。 + +## 参考资料 + +- [RFC 1035: Domain Names - Implementation and Specification](https://www.rfc-editor.org/rfc/rfc1035) +- [RFC 2131: Dynamic Host Configuration Protocol](https://www.rfc-editor.org/rfc/rfc2131) diff --git a/tools/diagram/src/dhcp.svg b/tools/diagram/src/dhcp.svg new file mode 100644 index 00000000..05108bca --- /dev/null +++ b/tools/diagram/src/dhcp.svg @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + DHCP:新接入的主机获取 IP 地址 + + 客户端(还没有 IP) + + + DHCP 服务器 192.168.1.1 + + + ① Discover 0.0.0.0:68 → 255.255.255.255:67 + 广播:有没有 DHCP 服务器? + + ② Offer 可以用 192.168.1.100,租期 1 天 + 附带子网掩码、网关、DNS 服务器 + + ③ Request 我要 192.168.1.1 提供的这个地址 + 仍是广播,其它服务器收回提议 + + ④ Ack 确认,从现在起租期 1 天 + 客户端开始使用这个地址 + 前两步用广播是因为客户端还没有地址,也不知道服务器在哪;租期过半时客户端会向同一台服务器申请续租。 + diff --git a/tools/diagram/src/dns-resolve.svg b/tools/diagram/src/dns-resolve.svg new file mode 100644 index 00000000..b814d249 --- /dev/null +++ b/tools/diagram/src/dns-resolve.svg @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + DNS 解析 www.example.com + + + + + 主机 + 先查浏览器缓存、 + 系统缓存和 hosts + + + + + + + + + + 本地 DNS 服务器 + 运营商或公司提供 + + + + + + + 根服务器 + a.root-servers.net + + + 去问 com 的服务器 + a.gtld-servers.net 等 + + + + + + + com 顶级域服务器 + a.gtld-servers.net + + + 去问 example.com 的服务器 + hera.ns.cloudflare.com 等 + + + + + + + 权威服务器 + hera.ns.cloudflare.com + + + www.example.com 的 A 记录 + 104.20.23.154,TTL 300 + + ① 递归查询 + + ④ 返回结果 + ② 迭代查询:每台服务器 + 只告诉下一步去问谁 + ③ 按 TTL 缓存 300 秒 + 图中的服务器和 TTL 是本机用 dig 逐级查询的结果:根服务器和 com 服务器返回的是下一级的 NS 记录(缓存 2 天), + 只有权威服务器的回答带有 aa(权威回答)标志。缓存命中时,前面任何一级都可以直接返回,不必走完全程。 + diff --git a/tools/diagram/src/email-flow.svg b/tools/diagram/src/email-flow.svg new file mode 100644 index 00000000..29344609 --- /dev/null +++ b/tools/diagram/src/email-flow.svg @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + 电子邮件:alice@a.com 发信给 bob@b.com + + + alice + 用户代理 + + + + + + + + + + a.com 邮件服务器 + + + + + + + + + + b.com 邮件服务器 + + + bob + 用户代理 + + + SMTP + + + SMTP(端口 25) + 先查 b.com 的 MX 记录 + 找到对方的邮件服务器 + + POP3 或 IMAP + bob 主动来取 + 发送和服务器之间的转发用 SMTP,是“推”;收件人读取用 POP3 或 IMAP,是“拉”。 + 邮件先存放在收件方的服务器上,bob 不在线也不影响 alice 发信。 + (用户代理到发件服务器之间通常使用端口 587 并要求登录。) + diff --git a/tools/diagram/src/ftp-modes.svg b/tools/diagram/src/ftp-modes.svg new file mode 100644 index 00000000..281bf44a --- /dev/null +++ b/tools/diagram/src/ftp-modes.svg @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + FTP 的主动模式与被动模式 + 主动模式 + + + + + 客户端 + + + + + + + + + + 服务器 + + 控制连接 → 21 + PORT 192,168,1,10,195,81 + + 数据连接 20 → 50001 + 服务器主动连接客户端的 50001, + 客户端的防火墙要放行 + 被动模式 + + + + + 客户端 + + + + + + + + + + 服务器 + + 控制连接 → 21 + PASV → 227 (…,195,82) + + 数据连接 → 50002 + 客户端主动连接服务器的 50002, + 服务器要开放一段端口 + PORT 和 PASV 的回复中,最后两个数字表示端口:195 × 256 + 81 = 50001,195 × 256 + 82 = 50002。 + 客户端通常在 NAT 和防火墙之后,服务器连不进来,所以现在多用被动模式。 + diff --git a/tools/diagram/src/mime.svg b/tools/diagram/src/mime.svg new file mode 100644 index 00000000..7073e718 --- /dev/null +++ b/tools/diagram/src/mime.svg @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + MIME:把非 ASCII 内容编码成 ASCII 字符 + 邮件主题 + + 你好 + + UTF-8 编码 + + e4 bd a0 e5 a5 bd + + Base64 + + 5L2g5aW9 + + 邮件首部 + + =?utf-8?b?5L2g5aW9?= + SMTP 最初只能传送 7 位 ASCII 文本。MIME 不改变 SMTP,只规定如何把中文、图片、附件等内容编码成 ASCII: + Base64 把每 3 个字节变成 4 个可打印字符,6 个字节的“你好”编码后是 8 个字符;收件方按首部中注明的 + 字符集和编码方式还原。 + diff --git a/tools/diagram/src/url-timeline.svg b/tools/diagram/src/url-timeline.svg new file mode 100644 index 00000000..f7faea58 --- /dev/null +++ b/tools/diagram/src/url-timeline.svg @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + 访问 https://www.example.com/ 的耗时(本机一次实测,RTT 约 200 ms) + DNS 解析 + + 10 ms,命中缓存 + TCP 三次握手 + + 1 个 RTT + TLS 1.3 握手 + + 1 个 RTT + 请求到首字节 + + 1 个 RTT + 服务器处理 + + 0 ms + + 100 ms + + 200 ms + + 300 ms + + 400 ms + + 500 ms + + 600 ms + + curl -w 测得:time_connect 0.210 s、time_appconnect 0.423 s、time_starttransfer 0.629 s。 + HTTPS 首次请求至少要 3 个 RTT 才能收到响应,这也是连接复用、TLS 会话恢复和 HTTP/3 要解决的问题。 +