【网络通信】从IP报文到应用层协议:一文彻底搞懂网络通信的完整体系
本文目标: 读完这篇文章,你将不再靠“感觉”理解网络,而是能用协议栈的视角,清晰回答“数据到底怎么走”的每一个细节。我们会从最底层的电信号,一路拆解到浏览器里的HTTP报文,顺带把内核态和用户态的边界也一并讲透。
作者介绍
哈喽,我是 CodeStats。
一个在底层技术上“考古”了四年的硬核爱好者,也是 WWAIC(全周项目AI编程) 范式的提出者和实践者。我曾手写过一个完整的 Java Web 框架(从 IoC 容器到嵌入式 Tomcat,代码全开源),也喜欢用通俗的语言拆解 CPU、JVM、操作系统的运行本质。
我一直相信,计算机科学没有魔法。所有看似神奇的效果——无论是 java -jar 一键启动,还是多线程自动切换——底层都是简单的规则层层组合。
网络也不例外。今天,我们就从最底层的 IP 报文 出发,一路拆解到常用的应用层命令,把整个通信体系彻底“扒干净”。
🎯 通过本文,你将获得什么?
-
✅ 掌握 TCP/IP 协议栈 的分层逻辑,以及每一层到底“干脏活”的细节
-
✅ 彻底搞懂 两台电脑通信 的全过程(从敲下回车到收到响应,精确到每个字节的封装)
-
✅ 弄清楚 ping 和 traceroute 背后完全不同的工作原理,不再混为一谈
-
✅ 理解为什么 telnet 能测端口,以及它为什么既是“服务”又是“工具”
-
✅ 了解操作系统默认携带的协议和服务,不再对“系统自带命令”感到陌生
-
✅ 区分
scp、curl、wget三个极易混淆的命令,根据场景选对工具 -
✅ 彻底分清 内核态与用户态 的边界——知道哪些是系统写死的,哪些是我们后装的
📑 提问目录
| 序号 | 问题 |
|---|---|
| ① | 两台电脑是如何完成通信的? |
| ② | ping 和 traceroute 命令有何区别? |
| ③ | telnet 是如何实现监测端口的?为什么说 telnet 是服务? |
| ④ | 操作系统默认会带哪些服务和协议实现? |
| ⑤ | scp、curl 和 wget 有何区别? |
| ⑥ | 这些协议和工具,到底是内核态执行还是用户态新增? |
① 两台电脑是如何完成通信的?
这个问题是整个网络体系的基石。要回答它,必须从TCP/IP协议栈的分层模型说起。网络上传输的数据就像一件包裹,每经过一层就套上一个“信封”,到达目的地后再逐层拆开。
1.1 协议栈:网络通信的“分层哲学”
TCP/IP协议栈采用分层解耦的设计,将复杂的网络通信拆解为独立层次。最经典的是四层模型:
| 层级 | 名称 | 核心职责 | 核心协议/概念 |
|---|---|---|---|
| 4 | 应用层 | 为用户提供网络服务接口 | HTTP、DNS、SSH、Telnet |
| 3 | 传输层 | 端到端的可靠(TCP)或不可靠(UDP)传输 | TCP、UDP |
| 2 | 网络层 | 寻址与路由转发 | IP、ICMP、ARP |
| 1 | 网络接口层 | 物理介质上的数据帧传输,MAC寻址 | 以太网、Wi-Fi |
1.2 一次完整通信:从敲下回车到收到响应
假设电脑A(IP: 192.168.1.10,MAC: AA:AA:AA:AA:AA:01)要访问电脑B(IP: 203.0.113.5)上的Web服务。电脑B在同一企业内网但跨网段,需要通过路由器转发。
第一步:应用层——发起请求(原始数据)
用户在浏览器输入 http://203.0.113.5/index.html,浏览器构造一个 HTTP请求报文,这串文本就是待传输的原始数据。
第二步:传输层——TCP三次握手 + 数据分段
HTTP报文被交给传输层。由于HTTP使用 TCP协议,通信前必须先建立连接(三次握手),确保双方都在线:
-
第一次握手(SYN):电脑A → 电脑B,发送
SYN=1, Seq=x(请求建立连接) -
第二次握手(SYN-ACK):电脑B → 电脑A,回复
SYN=1, ACK=x+1, Seq=y(同意建立) -
第三次握手(ACK):电脑A → 电脑B,发送
ACK=y+1(确认,连接正式建立)
TCP是面向连接的、可靠的传输协议。它通过三次握手建立连接,通过序列号保证数据有序,通过校验和保证不丢失。
连接建立后,TCP将HTTP报文分段(Segmentation),并为每段加上 TCP首部(20~60字节),包含关键字段:
-
源端口(随机,如 52341)
-
目标端口(80,标识Web服务)
-
序列号(保证有序到达)
-
校验和(检查数据是否损坏)
第三步:网络层——封装IP报文(逻辑寻址)
TCP段被交给网络层的 IP协议。IP为其加上 IP首部(20~60字节),包含:
-
源IP地址:
192.168.1.10 -
目标IP地址:
203.0.113.5 -
TTL(生存时间):初始设为64,每跳减1,防止死循环
IP的主要作用就是在复杂的网络环境中将数据包发给最终的目标地址,它只关心“终点在哪里”,不关心“下一跳是谁的MAC”。
第四步:网络接口层——封装成帧(物理寻址)
IP数据报被交给数据链路层。此时,电脑A需要知道“下一跳”是谁。它查看目标IP 203.0.113.5,发现不在自己网段(192.168.1.0/24),于是决定将数据包发给默认网关(假设IP是 192.168.1.1)。
关键动作:ARP请求
电脑A发出ARP广播:“谁的IP是 192.168.1.1?请告诉我你的MAC地址。”
网关回应:“我的MAC是 GG:GG:GG:GG:GG:01。”
电脑A将网关IP与MAC的映射存入ARP缓存表。
封装帧:
电脑A加上 帧首部(14字节),包含:
-
源MAC地址:
AA:AA:AA:AA:AA:01(电脑A) -
目标MAC地址:
GG:GG:GG:GG:GG:01(网关,即下一跳设备)
在以太网中,数据帧的传递依赖MAC地址,而IP地址只是逻辑终点。每一跳的转发,目标MAC地址都会被重写。
第五步:物理传输——比特流上路
帧被转换成电信号/光信号,通过网线/光纤发送到网关(路由器)。
第六步:逐跳转发(路由器的工作)
网关路由器收到数据帧:
-
检查帧:剥掉帧头,查看目标MAC是否是自己的(
GG:GG:GG:GG:GG:01),是则收下。 -
查看IP:查看目标IP
203.0.113.5。 -
查路由表:路由器查自己的路由表,发现去往
203.0.113.0/24网段需要从WAN口发出,下一跳是100.100.100.2(运营商路由器)。 -
重封装帧:路由器通过ARP获取下一跳
100.100.100.2的MAC(假设是OP:OP:OP:OP:OP:01),重新封装帧:-
源MAC:改为路由器的WAN口MAC
-
目标MAC:改为
OP:OP:OP:OP:OP:01 -
源IP与目标IP:保持不变(
192.168.1.10→203.0.113.5)
-
数据包就这样一跳一跳,每跳都重写MAC,直到到达目标电脑B所在的网关,再由该网关通过ARP找到电脑B的MAC,完成最终交付。
第七步:到达目标 + 逐层解封装
数据包到达电脑B后,逆向执行上述过程(网络接口层 → 剥帧,网络层 → 剥IP首部确认IP是自己,传输层 → TCP重组,应用层 → HTTP解析请求)。电脑B返回响应,走同样的路逆向回去——一次完整的网络通信就此完成。
② ping 和 traceroute 命令有何区别?
这两个命令都是网络排查的哼哈二将,但设计目标、工作原理截然不同。
2.1 核心区别一览
| 特性 | ping | traceroute |
|---|---|---|
| 工具定位 | 连通性验证工具 | 路径追踪与跳点定位工具 |
| 核心目标 | 测试目标是否可达、时延与丢包率 | 追踪数据包的完整路由路径 |
| 依赖协议 | ICMP(Echo) | ICMP(超时)+ UDP(Linux)或 ICMP(Windows) |
| 核心机制 | 发送ICMP Echo请求,等待Echo应答 | 利用IP首部的 TTL(生存时间) 字段逐跳探测 |
| 输出结果 | 时延(ms)、丢包率(%)、TTL值 | 每一跳的路由器IP及对应时延 |
2.2 ping 的原理
ping 只利用 ICMP回显请求(Type 8) 和 ICMP回显应答(Type 0) 两种报文。
工作流程:
本机发送Echo Request → 目标主机回复Echo Reply。本机根据往返时间(RTT)计算时延。
ping服务器在内核中处理ICMP,不经过传输层(不用TCP/UDP),所以它测的是“IP层通不通”,而不是“某个端口开没开”。
2.3 traceroute 的原理
traceroute 的灵魂是 TTL(Time To Live)。
工作流程:
-
发送第一个UDP包(或ICMP包),TTL=1 → 经过第一台路由器时TTL减为0 → 路由器丢弃包并返回 ICMP超时报文(Type 11) → 获取第一跳IP。
-
发送第二个包,TTL=2 → 获取第二跳。
-
以此类推,直到TTL足够到达目标主机。目标主机返回 ICMP端口不可达(因为traceroute通常故意发往一个高不可达端口)→ 探测结束。
2.4 ⚠️ 重要结论
Ping通 ≠ 业务通。Ping通只代表ICMP协议可达,但目标主机的防火墙可能封禁了80端口或22端口。业务通必须基于应用层协议+特定TCP端口验证。
③ telnet 是如何实现监测端口的?为什么说 telnet 是服务?
3.1 telnet 的“双重身份”
很多人对telnet的认知是混乱的,因为它确实具有双重身份:
-
身份一(协议/服务):它是
TELecommunication NETwork协议,用于远程终端登录,监听端口 23。作为服务端,它是一个长期运行的守护进程(如telnetd)。 -
身份二(客户端工具):我们命令行敲的
telnet命令,是一个通用的TCP客户端。
3.2 telnet 监测端口的原理
telnet 底层完全依赖TCP协议。执行 telnet [IP] [端口] 时:
-
telnet客户端向目标IP:端口发起TCP三次握手(SYN → SYN-ACK → ACK)。
-
握手成功 → 命令行显示
Connected to xxx→ 端口开放。 -
握手失败/超时 → 报错
Connection refused或Connection timed out→ 端口未开放或防火墙拦截。
这也是为什么telnet常用于测试TCP端口——它本质上是利用操作系统内核的TCP连接能力,验证端口是否在监听。
3.3 为什么说它是“服务”?
因为历史上它遵循 C/S架构:
-
Telnet客户端:
telnet命令。 -
Telnet服务端:
telnetd守护进程,监听23端口,接收客户端输入并执行shell命令。
当我们用 telnet 80 测试Web端口时,并没有开启telnet服务端,我们只是借用了客户端的TCP连接能力。如今telnet远程登录已被 SSH(加密) 淘汰,但它的“端口探测”功能依然好用。
④ 操作系统默认会带哪些服务和协议实现?
4.1 内置核心协议栈(内核态)
所有现代操作系统(Windows、Linux、macOS)内置完整的 TCP/IP协议栈:
| 协议 | 层级 | 作用 |
|---|---|---|
| IP | 网络层 | 无连接、不可靠的尽力交付,负责跨网络寻址 |
| ICMP | 网络层 | 差错报告与控制(ping、traceroute的基础) |
| ARP | 网络层/链路层 | 将IP地址解析为MAC地址(局域网通信必备) |
| TCP | 传输层 | 面向连接、可靠传输(HTTP/SSH/SMTP的底层) |
| UDP | 传输层 | 无连接、高效传输(DNS/DHCP/视频流的底层) |
4.2 用户态默认系统服务
| 服务 | 协议/端口 | 作用 |
|---|---|---|
| DNS Client | UDP/TCP 53 | 域名解析缓存服务,将域名转为IP |
| DHCP Client | UDP 67/68 | 自动从路由器获取IP地址、子网掩码、网关 |
| mDNS / NetBIOS | UDP 5353 / 137-138 | 局域网内设备发现(如AirDrop、网络邻居) |
4.3 默认携带的命令行工具
| 工具 | 定位 | 是否默认安装 |
|---|---|---|
ping |
ICMP连通性测试 | ✅ 全平台 |
tracert / traceroute |
路由路径追踪 | ✅ 全平台 |
telnet |
TCP端口测试(客户端) | ⚠️ Windows需手动启用(控制面板-功能),Linux默认有 |
nslookup / dig |
DNS查询工具 | ✅ Windows有nslookup,Linux有dig |
ssh / scp |
安全远程连接/文件传输 | ✅ Linux/macOS默认有,Windows需安装OpenSSH组件 |
curl / wget |
HTTP交互与下载 | ⚠️ Windows10+内置curl,Linux通常自带curl和wget |
⑤ scp、curl 和 wget 有何区别?
这三个命令经常被混用,但设计的原点完全不同。
5.1 核心区别一览
| 特性 | scp | wget | curl |
|---|---|---|---|
| 核心定位 | 安全文件传输(复制) | 文件下载工具 | 多协议数据交互(瑞士军刀) |
| 底层协议 | SSH(端口22,加密隧道) | HTTP / HTTPS / FTP | 20+种:HTTP/HTTPS/FTP/SFTP/SCP/POP3等 |
| 主要用途 | 主机间复制文件 | 从网络下载文件到本地 | API交互、上传下载、网页抓取、调试 |
| 断点续传 | ❌ 不支持 | ✅ 支持(-c) |
✅ 支持(-C -) |
| 上传能力 | ✅ 直接支持(本地→远程) | ❌ 不支持上传(仅下载) | ✅ 支持(-T / -F POST上传) |
| 输出详细度 | 仅进度条 | 下载进度及基本信息 | 可输出响应头、Cookie、详细Debug信息 |
| 适用人群 | 运维、系统管理员 | 普通用户、脚本下载 | 开发者、API测试工程师 |
5.2 场景选型指南
-
场景A:两台Linux服务器之间传文件(小文件) → 用
scp。bash
scp -P 2222 /local/file.txt root@192.168.1.100:/remote/
-
场景B:从互联网下载一个安装包 → 用
wget,简单直接,支持断点续传。bash
wget -c https://example.com/large.iso
-
场景C:调试RESTful API,发送JSON数据 → 用
curl,灵活处理Header、请求体、超时设置。bash
curl -X POST -H "Content-Type: application/json" -d '{"name":"test"}' https://api.example.com/v1/data -
场景D:单纯爬取网页源码做分析 →
curl配合-L跟随重定向,输出到stdout便于管道处理。
⑥ 这些协议和工具,到底是内核态执行还是用户态新增?
这个问题切中了操作系统的核心边界。明确答案:协议栈跑在内核态;命令工具跑在用户态。
它们之间靠 系统调用(System Call) 来通信。
6.1 哪些跑在“内核态”?(操作系统内核自带,不可新增)
内核态拥有访问硬件(网卡、内存)的最高权限。以下逻辑永远运行在内核中,你无法通过安装软件来替换它们:
-
IP协议:负责寻址和路由转发。
-
ICMP协议:处理
ping和traceroute底层的差错报文。 -
ARP协议:负责IP到MAC的地址解析(局域网通信的基石)。
-
TCP/UDP协议:管理端口监听、三次握手、滑动窗口、重传计时器等复杂状态机。
底层真相:当你打开浏览器访问网页时,你的代码(用户态)并不直接操作网卡。而是通过调用内核提供的 Socket API(套接字接口),把数据交给内核中的TCP/IP栈,由内核负责把数据切成报文、加上校验和、驱动网卡发出去。
6.2 哪些跑在“用户态”?(我们敲的命令,可新增)
你提到的所有命令工具,本质上都是存储在硬盘上的二进制可执行文件。当你敲下回车时,操作系统会为它们创建一个进程,它们运行在用户态,没有任何权限直接触碰网卡。
-
ping/traceroute:虽然是用户态进程,但它们需要调用内核的原始套接字(Raw Socket),因为ICMP报文只能由内核生成。它们是“借内核的手”来发包。 -
telnet/scp/curl/wget:纯用户态应用。它们只是调用了标准的connect()、send()、recv()等系统调用,将数据丢给内核的TCP协议栈,由内核完成真正的收发。
6.3 关于“新增”(用户态新增,而非内核态)
这是一个极易混淆的点:
-
内核态的协议无法“新增”:你不会去给Linux内核“安装”一个TCP/IP模块,因为它是内核源码编译时就写死的核心组件。
-
用户态的工具需要“新增”:如果系统没有
curl或wget,你需要用包管理器(如apt install curl)去安装。这个操作是将二进制文件写入/usr/bin/目录,属于用户态新增,绝不会动内核代码。
唯一的例外(内核模块):内核虽然固定,但可以通过
modprobe动态加载内核模块(LKM)。比如iptables的过滤模块、特殊的网络过滤驱动,这些属于“内核态的热插拔新增”。但你所列的这些标准协议和工具,均不在此列。
6.4 为什么内核态不能乱动?(安全与稳定)
如果允许用户随意“新增”或修改内核协议栈,那么一个进程崩溃就会导致整个操作系统蓝屏/死机。
设计铁律:
-
内核态只负责“干活”(发送比特流、管理定时器)。
-
用户态只负责“提需求”(我要访问百度、我要下载文件)。
📊 最终速查表
| 组件名称 | 运行态 | 是否随系统自带 | 可否用户态新增/安装 |
|---|---|---|---|
| TCP/IP 协议栈 | 内核态 | ✅ 固写在内核 | ❌ 绝不可新增 |
| ICMP/ARP 协议 | 内核态 | ✅ 固写在内核 | ❌ 绝不可新增 |
ping / traceroute |
用户态(依赖Raw Socket) | ✅ 默认自带 | ⚠️ 部分极简系统需安装 iputils-ping |
telnet 客户端 |
用户态 | ⚠️ Windows需启用,Linux通常自带 | ✅ 需要时可新增 |
curl / wget |
用户态 | ⚠️ 新版Windows自带curl,Linux通常自带 | ✅ 若无则需新增 |
scp / ssh |
用户态(依赖OpenSSL) | ⚠️ 需安装 openssh-client |
✅ 若无则需新增 |
一句话概括:内核是“高速铁路的钢轨和调度系统”,工具是“跑在这条铁路上的各类列车”。你可以随时增购(安装)新列车,但你绝不能在运行中擅自改变钢轨的铺设。
📝 全文总结
从最底层的电信号到顶层的浏览器页面,网络通信就是一场层层封装、逐跳转发、层层解封的接力赛。
-
① 通信本质:应用数据 → TCP分段(端口+可靠)→ IP寻址(逻辑终点)→ MAC逐跳(物理下一跳)。
-
② Ping vs Traceroute:Ping测“通不通”(ICMP响应),Traceroute测“怎么走”(TTL耗尽)。
-
③ Telnet测端口:借TCP三次握手验证端口状态,它本身是一个被SSH淘汰但保留了探测功用的C/S服务。
-
④ 操作系统默认:内置TCP/IP栈、ICMP、ARP,以及ping/tracert/telnet/nslookup等工具,开箱即用。
-
⑤ SCP vs Wget vs Curl:SCP传文件(SSH加密),Wget纯下载(简单专注),Curl通吃API(多协议全能)。
-
⑥ 内核态 vs 用户态:IP/TCP/ARP等协议固化在内核,不可新增;curl/scp等工具运行在用户态,按需安装。
记住这句话:IP决定终点,MAC决定下一跳,端口决定应用,协议决定规则,内核执行硬逻辑,用户态执行软需求。
如果这篇文章帮你撕开了网络通信的黑盒,欢迎点赞、收藏、转发! 有任何疑问或者想深究的底层细节(比如TCP的滑动窗口、HTTPS的TLS握手),欢迎在评论区留言,我们一起在底层“考古”。
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐

所有评论(0)