网络基础与 OSI/TCP-IP 协议栈

从零理解计算机网络的分层模型,掌握数据包的封装解封装过程、各层 PDU 与 MTU 的完整流转

理解网络编程的起点是理解协议栈的分层思想。每一层隐藏了底层的实现细节,通过标准化的接口为上层提供服务。

一、OSI 七层模型 vs TCP/IP 四层模型

1.1 分层对照

┌──────────────┬──────────────────────────────────┬──────────────────┐
│    OSI       │              功能                  │    TCP/IP        │
├──────────────┼──────────────────────────────────┼──────────────────┤
│ 7 应用层     │ HTTP、FTP、SSH、gRPC、WebSocket    │                  │
│ 6 表示层     │ 数据格式、加密解密、压缩           │   应用层         │
│ 5 会话层     │ 会话建立、管理、终止               │                  │
├──────────────┼──────────────────────────────────┼──────────────────┤
│ 4 传输层     │ TCP、UDP、端口号                   │   传输层         │
├──────────────┼──────────────────────────────────┼──────────────────┤
│ 3 网络层     │ IP、ICMP、路由选择、子网划分       │   互联网层       │
├──────────────┼──────────────────────────────────┼──────────────────┤
│ 2 数据链路层 │ MAC 地址、以太网、ARP、交换机      │   网络接口层     │
│ 1 物理层     │ 网线、光纤、无线、比特流传输       │                  │
└──────────────┴──────────────────────────────────┴──────────────────┘

1.2 分层数据交换逻辑

发送方                                         接收方
  │                                              ▲
  │  Application Data                            │  Application Data
  ▼                                              │
┌──────┐                                       ┌──────┐
│ HTTP  │  ← 应用层:HTTP 请求报文              │ HTTP │
├──────┤                                       ├──────┤
│ TCP   │  ← 传输层:Segment(段)               │ TCP  │
├──────┤                                       ├──────┤
│ IP    │  ← 网络层:Packet(包)                │ IP   │
├──────┤                                       ├──────┤
│ ETH   │  ← 链路层:Frame(帧)                 │ ETH  │
└──────┘                                       └──────┘
  │                                              ▲
  ▼  物理层传输                                  │

二、数据封装与解封装

2.1 封装过程

应用层数据(Payload)
    │
    ▼  + TCP Header(20-60 bytes)
传输层段(Segment)
    │
    ▼  + IP Header(20 bytes)
网络层包(Packet)
    │
    ▼  + ETH Header(14 bytes) + ETH Trailer(4 bytes)
链路层帧(Frame)
    │
    ▼  转化为比特流发送
物理层

2.2 各层 PDU(Protocol Data Unit)

层次名称标识说明
应用层Data / MessageHTTP 请求/响应体
传输层SegmentPortTCP 段/UDP 数据报
网络层PacketIP 地址IP 数据报
链路层FrameMAC 地址以太网帧
物理层Bit电信号/光信号比特流

2.3 Wireshark 实际观察

Frame 42: 1514 bytes on wire          ← 链路层帧
Ethernet II, Src: aa:bb:cc:dd:ee:ff   ← 以太网头部
Internet Protocol Version 4             ← IP 头部
Transmission Control Protocol           ← TCP 头部
Hypertext Transfer Protocol             ← HTTP 数据

三、IP 协议核心

3.1 IPv4 报文头部

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Version|  IHL  |Type of Service|          Total Length         |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|         Identification        |Flags|      Fragment Offset    |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|  Time to Live |    Protocol   |         Header Checksum       |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                       Source Address                          |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                    Destination Address                        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

3.2 子网划分

// Java 中计算子网
public class SubnetUtils {
    
    public static void main(String[] args) {
        // CIDR 表示法:192.168.1.0/24
        // 网络地址:192.168.1.0
        // 子网掩码:255.255.255.0(前 24 位为 1)
        // 可用主机数:2^(32-24) - 2 = 254
        
        int prefix = 24;
        int hostBits = 32 - prefix;
        int hostCount = (1 << hostBits) - 2;  // 减去网络地址和广播地址
        System.out.println("可用主机数: " + hostCount);  // 254
        
        // 判断 IP 是否在同一子网
        String ip1 = "192.168.1.100";
        String ip2 = "192.168.1.200";
        String mask = "255.255.255.0";
        
        int network1 = ipToInt(ip1) & ipToInt(mask);
        int network2 = ipToInt(ip2) & ipToInt(mask);
        System.out.println("同子网: " + (network1 == network2));
    }
    
    static int ipToInt(String ip) {
        String[] parts = ip.split("\\.");
        return (Integer.parseInt(parts[0]) << 24)
             | (Integer.parseInt(parts[1]) << 16)
             | (Integer.parseInt(parts[2]) << 8)
             | Integer.parseInt(parts[3]);
    }
}

3.3 IPv6 特点

特性IPv4IPv6
地址长度32 位128 位
地址数量约 43 亿3.4 × 10^38
头部长度可变(20-60 bytes)固定(40 bytes)
安全性IPsec 可选IPsec 内置
表示格式点分十进制冒号分隔十六进制
示例 IPv6 地址:
完整:2001:0db8:85a3:0000:0000:8a2e:0370:7334
压缩:2001:db8:85a3::8a2e:370:7334

四、ARP 协议

4.1 地址解析过程

主机 A(192.168.1.10)需要发送数据给主机 B(192.168.1.20)

1. A 检查 ARP 缓存,无 B 的 MAC 地址
2. A 发送 ARP 请求(广播):
   "谁的 IP 是 192.168.1.20?告诉 192.168.1.10(MAC: aa:bb:cc:dd:ee:ff)"
3. 所有主机收到请求,只有 B 响应(单播):
   "我是 192.168.1.20,MAC 是 11:22:33:44:55:66"
4. A 将 B 的 IP-MAC 映射存入 ARP 缓存
5. A 发送数据帧给 B

4.2 Java ARP 操作

// 通过 InetAddress 获取 MAC 地址(平台依赖)
InetAddress addr = InetAddress.getByName("192.168.1.1");
NetworkInterface ni = NetworkInterface.getByInetAddress(addr);
byte[] mac = ni.getHardwareAddress();

// 使用 ProcessBuilder 执行 arp 命令(Linux/macOS)
Process process = new ProcessBuilder("arp", "-a").start();
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
    System.out.println(line);
}

五、ICMP 与 Ping

// Java 中使用 ProcessBuilder 执行 ping
public class PingTest {
    
    public static boolean ping(String host, int timeoutMs) throws Exception {
        ProcessBuilder pb = new ProcessBuilder("ping", "-c", "1", "-W", String.valueOf(timeoutMs / 1000), host);
        Process process = pb.start();
        
        boolean finished = process.waitFor(timeoutMs + 1000, TimeUnit.MILLISECONDS);
        if (!finished) {
            process.destroyForcibly();
            return false;
        }
        
        return process.exitValue() == 0;
    }
    
    // 使用 isReachable(基于 ICMP 或 TCP echo)
    public static boolean isReachable(String host, int timeoutMs) throws Exception {
        return InetAddress.getByName(host).isReachable(timeoutMs);
    }
    
    public static void main(String[] args) throws Exception {
        System.out.println(ping("baidu.com", 3000));
        System.out.println(isReachable("baidu.com", 3000));
    }
}

六、MTU 与分片

6.1 MTU(Maximum Transmission Unit)

接口类型默认 MTU
以太网1500 bytes
PPPoE1492 bytes
IEEE 802.112304 bytes
回环接口65536 bytes
Jumbo Frame9000 bytes

6.2 路径 MTU 发现

发送方                                    接收方
  │ ─── 发送 DF=1(Don't Fragment)的包 ───→ │
  │                                         │
  │ ←── 收到 ICMP "Fragmentation Needed" ───│  MTU 只有 1400
  │                                         │
  │ ─── 发送 1400 bytes 的包 ─────────────→ │
  │                                         │
// Java Socket 设置 MTU
Socket socket = new Socket();
socket.setReceiveBufferSize(65536);
socket.setSendBufferSize(65536);

// NIO SocketChannel
SocketChannel channel = SocketChannel.open();
channel.socket().setReceiveBufferSize(65536);

七、常用网络工具

工具用途示例
ping测试连通性ping -c 4 baidu.com
traceroute路由追踪traceroute baidu.com
netstat查看连接netstat -tlnp
ss替代 netstatss -tlnp
tcpdump抓包tcpdump -i eth0 port 80
Wireshark图形化分析分析 pcap 文件
telnet测试端口telnet baidu.com 80
nc网络瑞士军刀nc -zv baidu.com 80
curlHTTP 请求curl -v https://api.example.com
nmap端口扫描nmap -sS 192.168.1.1

八、总结

层次核心协议关键概念
应用层HTTP/HTTPS、gRPC、DNS请求/响应、RPC
传输层TCP、UDP端口、连接、可靠性
网络层IP、ICMP、ARP地址、路由、分片
链路层Ethernet、Wi-FiMAC、帧、交换机

协议栈的分层设计体现了软件工程中"关注点分离"的核心思想。每一层专注于自己的职责,通过标准化的接口与上下层交互,使得整个网络通信系统既灵活又可靠。

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「network」更多文章

  1. 网络安全:TLS/SSL、证书与加密通信
  2. 负载均衡算法与高可用架构
  3. DNS 系统与智能解析