Files
cs-note/hhs/NETWORK/01-基础概念/01-OSI与TCP-IP模型对比.md
T
2026-05-24 11:42:38 +08:00

9.0 KiB
Raw Blame History

tags, create time
tags create time
计算机网络
OSI模型
TCP/IP
网络分层
2026-05-17 22:10

OSI 七层 vs TCP/IP 四层模型

概述

OSI(Open Systems Interconnection)和 TCP/IP 是理解计算机网络的两种经典分层模型。OSI 提供了一套理论化的参考框架,而 TCP/IP 则是实际运行在因特网上的协议栈。理解两者的映射关系,有助于我们在设计系统和排查问题时建立正确的抽象层次。

[!QUESTION] 为什么现实用五层模型而不是 OSI? OSI 的七层理论很完美,但实现起来复杂到几乎不可能。TCP/IP 只有四层,又太粗。于是教学上采用折中的「五层模型」:把 OSI 的应用/表示/会话三层合并为应用层,保留传输层、网络层、链路层、物理层——刚好够表达所有关键概念。

OSI 七层模型

分层结构

层级 名称 PDU(协议数据单元) 核心职责
7 应用层 数据(Data) 为用户提供网络服务接口(HTTP、FTP、SMTP)
6 表示层 数据 数据格式转换、加密解密、压缩解压
5 会话层 数据 建立/维护/终止会话(会话令牌、检查点)
4 传输层 段(Segment) 端到端可靠传输、流量控制、差错控制
3 网络层 包(Packet) 路由选择、逻辑寻址(IP 地址)
2 数据链路层 帧(Frame) 物理寻址(MAC)、相邻节点间的帧传输
1 物理层 比特(Bit) 电气特性、机械接口、光电信号转换
graph BT
    subgraph "传输中封装"
        D["应用层 Data"] --> L6["表示层: 加密+压缩"]
        L6 --> L5["会话层: 建立/维护/结束会话"]
        L5 --> S["传输层 Segment"]
        S --> P["网络层 Packet"]
        P --> F["链路层 Frame"]
        F --> B["物理层 Bitstream"]
    end

    style D fill:#DDA0DD
    style S fill:#FFD700
    style F fill:#98FB98
    style B fill:#B0C4DE

每层经典协议对照表

层 协议 作用场景
应用层 HTTP, DNS, SMTP, FTP, SSH, WebSocket 应用间通信
表示层 TLS/SSL, JPEG, MPEG, ASN.1 数据格式化与加密
会话层 NetBIOS, RTP, SIP 多路复用与同步
传输层 TCP, UDP, SCTP 端到端数据传输
网络层 IP, ICMP, IGMP, ARP* 跨网段路由转发
链路层 Ethernet, Wi-Fi (802.11), VLAN, PPP 相邻设备帧传输
物理层 USB, RS-232, 光纤, Cat6 网线 物理信号传输

[!note] ARP 到底在第几层? ARP 将 IP 地址解析为 MAC 地址,跨越了网络层和链路层的边界。OSI 将其放在网络层下方、链路层上方的"夹层"位置。现代观点常把它视为网络层的一部分。

TCP/IP 四层模型

分层结构

层级 对应 OSI 核心协议 核心职责
应用层 7+6+5 层合并 HTTP, DNS, SMTP, SSH 面向应用的协议栈
传输层 4 层 TCP, UDP 端到端连接管理
网络层 3 层 IP, ICMP, ARP 分组路由与寻址
网络接口层 2+1 层合并 Ethernet, Wi-Fi 帧传输与物理介质

为何 OSI 没赢下标准之战

flowchart LR
    A["OSI 七层模型<br/>ISO 标准"] --> B{谁先落地?}
    B -->|"1970s 末"| C["TCP/IP 已部署在 ARPANET"]
    B -->|"1980s 后"| D["OSI 标准太多太复杂"]
    C --> E["事实标准 ✅"]
    D --> E
    style E fill:#98FB98,color:#000
  • 先发优势:ARPANET / Internet 先用上了 TCP/IP,基础设施已经建成
  • 简单粗暴:TCP/IP 只关心能不能跑通,不搞复杂的标准化流程
  • 开源免费:Berkeley BSD Unix 内嵌 TCP/IP 协议栈,免费分发
  • OSI 的反面教材:层层审批导致协议膨胀(X.400 邮件、X.25 分组交换),开发者根本懒得用

五层教学模型

这是教材中最常用的模型,取两者精华:

flowchart TD
    A["应用层 — Application<br/>HTTP DNS SMTP SSH FTP SMTP POP3 IMAP WebSocket"] --> T["传输层 — Transport<br/>TCP UDP SCTP"]
    T --> N["网络层 — Internet<br/>IP IPv6 ICMP ARP NAT"]
    N --> D["链路层 — Link<br/>Ethernet Wi-Fi 802.11 VLAN HDLC PPP"]
    D --> P["物理层 — Physical<br/>双绞线 光纤 无线电 IEEE 802.15"]
    style A fill:#DDA0DD
    style T fill:#FFD700
    style N fill:#87CEEB
    style D fill:#98FB98
    style P fill:#B0C4DE

[!QUESTION] 为什么是五层,不是三层或八层? 分层的本质是职责分离——每一层只关心自己该做的事,通过标准接口向上层提供服务。层数太少(如三层)会导致单层职责过重,排查问题困难;层数太多则引入不必要的抽象开销。五层是一个兼顾教学清晰度和工程实用性的"甜蜜点"。

三层模型横向对比

下面的表格将三种模型放在同一张表里,方便你快速查清某一层在不同模型中的对应关系:

功能域 OSI 层 五层模型 TCP/IP 层 典型协议/技术 封装单元
应用逻辑 7 应用层 应用层 应用层 HTTP, DNS, SMTP, SSH Data
数据表示 6 表示层 ↗ ↗ TLS/SSL, JPEG, ASN.1 Data
会话管理 5 会话层 ↗ ↗ NetBIOS, RTP, SIP Data
端到端传输 4 传输层 传输层 传输层 TCP, UDP, SCTP Segment
路由寻址 3 网络层 网络层 网络层 IP, ICMP, ARP Packet
帧传输 2 数据链路层 链路层 网络接口层 Ethernet, Wi-Fi, PPP Frame
物理信号 1 物理层 ↗ ↗ 光纤, 双绞线, 无线电 Bit

[!tip] ↗ 符号的含义 上表中 ↗ 表示"向上合并"——五层模型把 OSI 的表示层、会话层并入应用层;TCP/IP 模型进一步把数据链路层、物理层合并为网络接口层。合并不等于消除,这些功能仍然存在,只是不再单独成层。

数据包逐层穿越过程

以你发送一封电子邮件为例:

sequenceDiagram
    participant App as 你的邮件客户端
    participant T as TCP层
    participant I as IP层
    participant L as 以太网层
    participant Router as 路由器
    participant R as 接收方

    App->>T: SMTP 邮件内容 (Data)
    T->>T: 加 TCP 首部 (Header + Data → Segment)
    T->>I: 传递 Segment
    I->>I: 加 IP 首部 (Header + Segment → Packet)
    I->>L: 传递 Packet
    L->>L: 加以太网帧头帧尾 (Header + Packet + FCS → Frame)
    L->>Router: 通过网线发送 Frame
    Router->>Router: 拆帧 → 查路由表 → 重新封帧
    Router->>R: 转发给接收方
    R->>L: 解包 → IP层校验 → TCP重组 → 提取 SMTP
    R->>App: 邮件到达收件箱

[!tip] 封装 = 套娃;解封装 = 剥壳 每一层只知道自己那一层的 header 是什么格式,对其他层的内容一无所知。这就是层间透明原则。

[!QUESTION] 如果每一层都要加头部,开销岂不是很大? 没错。一个 1 字节的应用层数据,经过 TCP/IP/以太网三层封装后,可能膨胀到 50+ 字节(TCP 头 20B + IP 头 20B + 以太网帧头帧尾 18B)。这就是为什么对小数据量、低延迟场景,业界会选择 UDP(头部仅 8 字节)甚至 QUIC(合并传输层与加密层)来减少开销。

分层在代码中的体现

理解分层模型,不只是为了面试,它直接影响你在编程中需要关心什么、不需要关心什么:

package main

import (
    "fmt"
    "net"
)

func main() {
    // 传输层:你只需告诉 OS "用 TCP 连这个地址"
    // IP 路由、以太网帧封装、物理信号 —— 全部由内核和网卡处理
    conn, err := net.Dial("tcp", "example.com:80")
    if err != nil {
        panic(err)
    }
    defer conn.Close()

    // 应用层:你手动构造 HTTP 请求(Data 层的内容)
    request := "GET / HTTP/1.1\r\nHost: example.com\r\n\r\n"
    conn.Write([]byte(request))

    // 读取应用层响应 —— 下面的 Segment/Packet/Frame 已被内核剥壳
    buf := make([]byte, 4096)
    n, _ := conn.Read(buf)
    fmt.Println(string(buf[:n]))
}

这段代码里,程序员只和应用层(HTTP 报文)与传输层(Dial("tcp", ...))打交道。网络层以下的路由、帧封装、电信号转换完全由操作系统和硬件代劳——这就是分层带来的抽象红利。

[!QUESTION] 如果没有分层会怎样? 想象一下:每次发 HTTP 请求,你都要手动计算 IP 校验和、填写 MAC 地址、调制电信号……代码量和出错率会指数级上升。分层让我们可以只关注自己那一层,其余的交给下层实现。

关联笔记