OSI / TCP-IP 模型
OSI 用七层划分网络通信的职责,TCP/IP 把这些职责归为四层。本课使用 Ethernet + IP + TCP:TCP、IP、Ethernet 各增加一层封装,共三层。七个 OSI 名称不代表七个首部;会话层和表示层没有另加首部。
可以把 HTTP 请求看作包裹中的便条。TCP 端口写房间号,IP 写街道地址,Ethernet 写下一站的收件地址。中途的邮局拆下外袋,查看街道地址,再换一个外袋转发,无需打开便条。主机收到数据却没有程序接收时,也要按这些职责排查。
OSI 和 TCP/IP 如何分层
OSI 从上到下有七层:
- 应用层:程序要发送的消息,这里是
GET / HTTP/1.1。 - 表示层:数据格式与加密。TLS 在概念上承担这类职责;本课的明文 HTTP 不使用 TLS。
- 会话层:标识会话。本例由 TCP socket 标识通信,没有独立的 OSI 会话首部。
- 传输层:用端口区分同一主机上的程序。
- 网络层:用 IP 地址将包送往目标主机,跨越网络。
- 数据链路层:用下一跳的 MAC 地址跨越一段链路。
- 物理层:把数据编码为线路上的比特,不增加首部。
RFC 1122 的 TCP/IP 模型分为应用层、传输层、网际层和链路层。OSI 的会话层、表示层归入应用层,物理层归入链路层。本课仍执行三次封装。教材常见的五层模型合并了 OSI 的会话层和表示层,但保留物理层。
PDU(协议数据单元)指当前层处理的数据:消息 → TCP 段 → IP 包 → Ethernet 帧 → 比特。
代码中的 wrap 在应用层、表示层、会话层、物理层直接返回原值,只在传输层、网络层、链路层调用 Header(...)。循环结束后才调用 to_bits。HTTP 自己的首部属于这里的应用数据,不算另一层下层封装。
普通路由转发会去掉链路层封装,读取目标 IP,再为下一跳写入 Ethernet 首部,无需解析 TCP 或 HTTP。这里不考虑 NAT 或应用代理。
OSI / TCP-IP 模型逐步演示
默认选择 OSI 7 和 direct:发送 GET / HTTP/1.1,源为 10.0.0.2:49152,目标为 93.184.216.34:80。
- 显示分层。 客户端和源站各有七层空栈,每层标出对应的 TCP/IP 名称。
- 应用层写消息。 出现
GET / HTTP/1.1,首部计数为 0。HTTP 是本例的应用数据。 - 表示层。 层级亮起,数据不变。若使用基于 TCP 的 HTTPS,TLS 会承担加密职责,记录位于 TCP 内;当前请求是明文。
- 会话层。 TCP socket 已标识会话,不增加首部。
- 传输层封装。 加入 TCP:
sport=49152 dport=80。PDU 成为段,首部计数为 1。 - 网络层封装。 加入 IP:
10.0.0.2 → 93.184.216.34。PDU 成为包,计数为 2。 - 链路层封装。 加入从客户端 MAC 到源站 MAC 的 Ethernet 首部。PDU 成为帧,计数为 3。
- 物理层编码。 帧变为比特标记。
to_bits只编码,内部仍是三层封装。 - 线路传输。 比特沿链路移动,两端的物理层亮起。
- 源站解码。 比特恢复为含三层封装的帧。
- 链路层解封装。 去掉 Ethernet;这一层不读取端口或 URL。
- 网络层解封装。 确认目标为本机,去掉 IP。
- 传输层解封装。 去掉 TCP,按端口 80 分发给监听 socket。PDU 恢复为消息。
- 会话层上行。 数据不变。
- 表示层上行。 数据不变。配置 HTTPS 时此处可表示解密职责;端口号本身不决定加密。
- 应用层读取。 得到客户端发送的
GET / HTTP/1.1,字节相同。 - 结束。 线路上有三个下层首部,模型有七个层名;会话层和表示层没有修改数据。
切换 TCP/IP 4,三次封装仍在,只去掉会话层和表示层上下行的四个职责展示步骤。
Via router 在发送后增加一跳。第一帧的目标 MAC 是路由器。路由器去掉 Ethernet,看到 dst 仍为 93.184.216.34,再换上下一跳的 Ethernet 首部。应用层和传输层不参与。真实 IPv4 路由器还会减少 TTL、更新首部校验和;目标地址不变不代表整个 IP 首部不变。
Skip transport 让 omit == "transport" 触发 continue,IP 直接封装 GET。接收端可以去掉 Ethernet 和 IP,但缺少 TCP 首部与目标端口,unwrap 报错,无法交给本例的 TCP 监听 socket。L1–L3 成功不代表应用交付成功。
七个层名为何只有三个首部
层名描述职责,首部数量由 wrap 的实际操作决定。第 4 步仍是 GET,第 7 步增加了三层,第 8 步把同一份数据编码为比特。切换 TCP/IP 只改变职责分组。
三个地址各有用途:MAC 指向下一跳,IP 指向目标主机,端口指向服务。普通路由转发后,抓包中的 Ethernet 首部改变,目标 IP 和 TCP 端口保留。排查时要区分“包到达主机”和“端口上有程序监听”。路由器只处理转发所需的层,无需理解应用消息。
边界情况
- 跳过传输层。 Ethernet 与 IP 仍可工作,但本例的 TCP 服务需要 TCP 首部和端口。其他 IP 协议、原始 socket 不在模型中,不能据此断言所有网络通信都需要端口。
- 经过路由器。 本例不使用 NAT,目标 IP 保留,下一跳 MAC 改变;真实 IPv4 的 TTL 也会改变。第一帧必须先交给路由器。
- 上行职责层。 去掉 TCP 后,会话层与表示层依次亮起,仍不修改数据,与下行一致。
- 物理层。
to_bits是编码。OSI 七层不意味着 Ethernet 帧包含七个通用首部。 - 固定请求。 本课不提供任意消息输入,以固定地址、端口和封装计数;可调整模型与路径。
常见错误
- 按层名数首部。 暂停在表示层,数据没有变大;到 Ethernet 时才完成第三次封装。
- 给 TLS 增加一个并列的 OSI 首部。 基于 TCP 的 TLS 位于 TCP 内。有解密密钥时,Wireshark 才能进一步显示其中的 HTTP;不会出现与 TCP 并列的通用“L6 首部”。
- 认为路由器必须读 HTTP。 普通转发无需进入应用层,否则路由器就得为它转发的每一种应用协议实现解析。
- 用 MAC 指定进程。 Ethernet 负责一跳交付;本例用 TCP 端口选择接收服务。
- 把 OSI 与 TCP/IP 当成两套竞争实现。 它们以不同粒度划分职责。本例的数据和封装操作相同。
模型的简化
本课展示职责,不模拟完整报文。真实 TCP 还有序号、校验和、选项、窗口缩放;IP 涉及 TTL、分片及 IPv4/IPv6 差异;Ethernet 可能包含 VLAN,并有帧尾。真实路径也常有多跳。Header("TCP") 只是标签,不代表一个完整的 20 字节 TCP 首部。IPv4 路由器更新 TTL 和首部校验和;IPv6 使用 Hop Limit,没有 IP 首部校验和。
在此 TCP/IP 对照中,TLS 和 HTTP/2 属于应用层范围。QUIC 是基于 UDP 的传输协议,不能套用本例的 TCP 封装路径。基于 TCP 的 HTTPS 将 TLS 记录放入 TCP;使用端口 443 本身不会启用加密。五层教材模型只是合并 OSI 的 L5、L6,因此本课未另设第三种展示。