当前位置: 首页 > news >正文

数据解封装:一条网络消息,怎样从网卡走到你的程序

文章目录

  • 一、从“收到一帧”开始:网络世界并不知道你是谁
  • 二、网卡接收帧后:操作系统先确认“这是什么协议”
  • 三、IP 层路由判断:这份数据是不是应该交给本机
  • 四、TCP 与 UDP:端口号决定“交给哪个程序”
  • 五、应用层处理:浏览器终于拿到了它真正关心的数据
  • 六、解封装真正告诉我们的:网络不是“发过去”,而是“逐层交接”

当我们在浏览器中打开一个网页、在微信里收到一条消息,或在终端里执行一次curl请求时,屏幕上看到的是“应用收到了数据”。但在操作系统内部,真正发生的事情远比这一句话复杂。

网络上传来的并不是一段直接交给浏览器或服务器程序的纯文本,而是一层又一层封装好的二进制数据。它先作为以太网帧到达网卡,再经过 IP 层判断目的地址与路由关系,随后由 TCP 或 UDP 根据端口号找到对应程序,最终才进入应用层协议处理逻辑。

这个过程通常被称为数据解封装。它和发送数据时的“逐层封装”正好相反:发送时不断加头部,接收时则不断识别、校验、剥离头部,并把真正有效的数据交给上层。

为了便于理解,本文用一个贯穿示例来说明:

你的浏览器访问https://example.com,服务器返回了一段 HTML 页面内容。

浏览器最终看到的是网页,但在到达浏览器之前,这段 HTML 已经经历了网卡、交换机、路由器、IP 协议、TCP 协议、TLS 协议和 HTTP 协议等多个环节。

一、从“收到一帧”开始:网络世界并不知道你是谁

计算机接入网络后,最先面对的不是“网页数据”或“聊天消息”,而是网卡不断接收到的二进制信号。

如果你使用的是网线,数据通过电信号在网线中传输;如果使用 Wi-Fi,数据则通过无线电波传输。无论底层介质是什么,网卡的任务都是把这些物理信号还原成一串可识别的比特,再组织成一帧一帧的数据。

在局域网中,最常见的是以太网帧。一个帧通常包含目标 MAC 地址、源 MAC 地址、协议类型、数据部分以及校验信息。

可以粗略理解为:

[目标MAC][源MAC][协议类型][上层数据][校验信息]

浏览器访问网站时,服务器返回的数据并不会直接写着“交给 Chrome”。它首先会被封装进一个网络帧中,通过交换机、路由器和运营商网络逐跳转发,最后抵达你的电脑网卡。

网卡收到帧之后,并不会立刻把所有内容都交给操作系统。它首先要判断:这是不是发给我的?

例如,你电脑网卡的 MAC 地址可能是:

AA-BB-CC-DD-EE-FF

如果收到的帧目标 MAC 地址正好是这个地址,网卡通常会继续接收。如果目标地址是广播地址,例如:

FF-FF-FF-FF-FF-FF

网卡也会接收,因为广播帧本来就是发给局域网中所有设备的。

如果目标 MAC 地址既不是本机地址,也不是广播或允许接收的多播地址,那么网卡通常会直接丢弃这帧数据。

这说明一个重要事实:网络中的第一层筛选,不是看 IP,不是看端口,而是先看二层地址,也就是 MAC 地址。

不过,现代网卡不会只做最简单的接收工作。为了减轻 CPU 负担,很多网卡支持硬件校验、分段卸载、校验和卸载以及中断合并等机制。简单来说,就是尽可能把重复而机械的处理交给硬件,让操作系统和 CPU 把更多时间留给真正的应用程序。

二、网卡接收帧后:操作系统先确认“这是什么协议”

网卡确认帧可以接收后,会把帧交给操作系统的网络协议栈。

此时,系统需要先确认这帧承载的是什么上层协议。以太网帧中有一个非常重要的字段,通常称为 EtherType,也就是“协议类型”。

常见的类型包括:

协议类型含义
IPv4这是一个 IPv4 数据包
IPv6这是一个 IPv6 数据包
ARP地址解析协议数据
VLAN带有虚拟局域网标记的帧

如果帧中标记的是 ARP,那么系统会交给 ARP 模块处理;如果标记的是 IPv4 或 IPv6,才会继续进入 IP 层。

例如,你的浏览器访问某个网站时,真正的 HTTP 数据一般不会直接出现在以太网帧中。帧的数据区域里通常装的是一个 IP 数据包,而 IP 数据包里面才继续装着 TCP 段,TCP 段里面才可能是 TLS 数据,TLS 数据内部才是 HTTP 内容。

整个关系可以用下面这张图表示:

ARP

IPv4 / IPv6

网卡收到以太网帧

目标 MAC 是否匹配

丢弃

识别 EtherType

交给 ARP 模块

进入 IP 层

检查目标 IP 与路由

进入 TCP / UDP

按端口分发给 Socket

应用层协议处理

这里可以看到,数据并不是一次性“交给浏览器”。它要经过多轮身份识别和协议判断。

从操作系统角度看,每一层都只关心自己应该关心的事情。

网卡层只关心帧和 MAC 地址;IP 层只关心 IP 地址、分片、路由和上层协议;TCP 或 UDP 层只关心端口、连接和数据完整性;应用程序才关心 HTTP、JSON、图片、视频、数据库请求等业务内容。

这种分层设计的价值很大。因为浏览器不需要理解网卡如何接收无线信号,网卡也不需要理解 HTTP 请求头,路由器更不需要知道某个网页里写了什么 HTML。

三、IP 层路由判断:这份数据是不是应该交给本机

通过以太网帧的识别之后,系统会进入 IP 层。

此时,操作系统从帧中取出 IP 数据包,并开始检查其中的重要字段,例如:

源 IP 地址 目的 IP 地址 协议字段 TTL 或 Hop Limit 分片标志 首部校验信息

假设你的电脑 IP 地址是:

192.168.1.10

而收到的数据包目的 IP 地址也是:

192.168.1.10

那么系统会认为这通常是发送给本机的数据,可以继续处理。

但现实中的情况并不总是这么简单。因为一台设备可能有多个网络接口,例如:

  • 有线网卡
  • Wi-Fi 网卡
  • VPN 虚拟网卡
  • Docker 虚拟网卡
  • 虚拟机网卡
  • 回环接口127.0.0.1

所以操作系统不能只靠“某一个 IP 地址是否相同”来判断,还需要结合本机路由表、接口状态、地址绑定关系和策略路由规则。

例如,当你同时开启 Wi-Fi 和 VPN 时,同一个应用程序发出的数据,可能根据路由规则走向不同网卡。访问公司内网的请求可能通过 VPN,访问普通网站的请求则通过家里的 Wi-Fi。

对于接收方向也是如此。系统需要确认这个目的 IP 是否属于本机,或者该数据是否需要由本机继续转发。

如果电脑开启了 IP 转发功能,例如它被配置成软路由、网关、VPN 服务器或 Docker 主机,那么收到的数据包可能并不是交给本机应用,而是需要继续转发到另一个网络接口。

这就是所谓的“路由判断”。

在普通个人电脑上,大多数进入本机的网络包都会满足两个条件:

第一,目的 MAC 地址被网卡接受。
第二,目的 IP 地址属于本机某个网络接口。

如果两个条件都满足,操作系统才会继续查看 IP 头部中的协议字段。

这个字段决定了下一步交给谁。

常见的情况包括:

IP 协议字段上层处理模块
TCP交给 TCP 协议栈
UDP交给 UDP 协议栈
ICMP交给 ICMP 模块
ESP可能交给 IPsec 处理
GRE可能交给隧道协议处理

例如,你执行:

pingwww.example.com

收到的不是 TCP 数据,也不是 UDP 数据,而是 ICMP 回应报文。

而你打开网页时,通常会进入 TCP;你使用很多实时音视频、游戏或 DNS 服务时,可能更多会进入 UDP。

因此,IP 层的核心任务不是理解业务数据,而是完成一次更高级别的判断:

这个包应该在本机继续处理,还是应该转发?
如果继续处理,下一层到底应该交给哪一种传输协议?

四、TCP 与 UDP:端口号决定“交给哪个程序”

进入 TCP 或 UDP 层后,数据终于开始接近具体应用程序。

很多初学者会认为,IP 地址已经能够定位一台电脑,那么数据自然就知道该交给哪个程序。实际上并不是。

一台电脑上可能同时运行很多网络程序:

  • 浏览器
  • 微信
  • VS Code
  • Nginx
  • MySQL
  • Docker 容器
  • 游戏客户端
  • 远程桌面服务

它们可能都使用同一个公网 IP 或局域网 IP。

因此,IP 地址只能定位到“哪台主机”,但不能定位到“哪个进程”。真正用于区分应用程序的,是端口号。

例如:

80 HTTP 443 HTTPS 22 SSH 53 DNS 3306 MySQL 3389 Remote Desktop

当 IP 层发现协议字段是 TCP 时,会把数据交给 TCP 模块。TCP 模块会读取 TCP 首部中的源端口与目的端口。

假设浏览器正在访问:

https://example.com

浏览器本地可能使用一个临时端口:

本机 IP:192.168.1.10 本机端口:52341 服务器 IP:93.184.216.34 服务器端口:443

这四个信息组合起来,通常被称为一个 TCP 连接的四元组:

源 IP + 源端口 + 目的 IP + 目的端口

对于客户端来说,服务器端口一般比较固定,例如 HTTPS 常用 443。客户端端口则通常由操作系统动态分配。

因此,当服务器返回数据时,目标信息可能是:

目标 IP:192.168.1.10 目标端口:52341

TCP 协议栈查找到这个连接后,才知道这份数据应该交给浏览器,而不是交给微信或其他程序。

TCP 的工作不只是“按端口找程序”。它还需要负责很多重要任务。

首先,它要检查序列号,确认数据是否按照正确顺序到达。网络中的数据包可能绕不同路径传输,因此先发出的包不一定先到。

其次,它要处理重传。如果某个包丢失,TCP 可以通过确认机制发现问题,并请求对方重新发送。

再次,它要处理流量控制和拥塞控制。接收端处理不过来时,可以通知发送端降低速度;网络拥塞时,TCP 也会主动调整发送节奏。

所以,对于浏览网页、传输文件、登录 SSH、访问数据库这些场景,TCP 更像是一条可靠的数据通道。

UDP 则不同。

UDP 也使用端口号把数据交给应用程序,但它通常不保证顺序、不保证重传,也不保证对方一定收到。它更轻量,延迟通常更低,适合一些强调实时性的业务,例如在线游戏、实时音视频、直播、DNS 查询和部分物联网场景。

可以把 TCP 和 UDP 简单理解为:

协议特点
TCP更可靠,重视完整性和顺序
UDP更轻量,重视速度和实时性

不过,这并不代表 UDP 一定“不可靠”。很多现代应用会在 UDP 之上自行实现确认、重传、加密和拥塞控制机制。QUIC 协议就是典型例子,HTTP/3 就基于 QUIC,而 QUIC 底层使用 UDP。

也就是说,端口分发只是传输层的一个基础职责,真正复杂的部分还包括连接状态、顺序恢复、错误检测、流量控制和安全协商。

五、应用层处理:浏览器终于拿到了它真正关心的数据

当 TCP 或 UDP 协议栈找到对应 Socket 后,数据就会进入应用程序。

这里的 Socket,可以理解为操作系统提供给程序的一种网络通信接口。浏览器、服务器、数据库、聊天软件都通过 Socket 接收和发送网络数据。

对于浏览器来说,收到数据后并不会直接显示出来。因为浏览器还需要继续完成应用层协议处理。

以 HTTPS 网站为例,数据大致会经历这样的过程:

TCP 数据 → TLS 解密与校验 → HTTP 响应解析 → HTML / CSS / JavaScript 处理 → 页面渲染

假设服务器返回:

HTTP/1.1 200 OK Content-Type: text/html <html> <body> Hello World </body> </html>

在真正到达浏览器渲染引擎之前,这段内容可能已经被 TCP 分成多个报文段,又被 IP 封装成多个数据包,再被放入多个以太网帧中。

浏览器不会直接看到“某一帧数据”。它通过操作系统提供的 Socket 接口持续读取一个逻辑上的字节流。

这也是 TCP 很重要的一个特点:对应用程序来说,它更像一条连续可靠的字节流,而不是一堆零散的数据包。

例如,服务器发送了 10KB 的 HTML 内容,浏览器可能并不会一次性收到完整 10KB。它可能先读到 2KB,再读到 3KB,随后又读到剩余部分。

因此,应用程序在处理网络数据时,不能简单认为“一次recv()就等于收到一条完整消息”。

这在编写网络程序时尤其重要。

例如,一个 TCP 服务器收到的数据可能是:

GET /index.html HTTP/1.1 Host: example.com

但由于网络分段关系,程序可能第一次只收到:

GET /index.html HT

第二次才收到:

TP/1.1 Host: example.com

所以应用程序必须自己根据协议规则判断“消息是否完整”。

HTTP 会通过请求行、头部、内容长度、分块传输等方式帮助程序识别消息边界;WebSocket 有自己的帧格式;数据库协议、Redis 协议、MQTT 协议也都有各自的消息结构。

最终,浏览器解析 HTML、加载 CSS、执行 JavaScript、请求图片和字体,再把页面绘制到屏幕上。

用户看到的是一个网页,但操作系统内部刚刚完成的是一整条协议链路:

网卡收帧 → 二层 MAC 判断 → IP 地址与路由判断 → TCP / UDP 传输层处理 → 端口找到对应 Socket → 应用协议解析 → 页面或业务逻辑呈现

六、解封装真正告诉我们的:网络不是“发过去”,而是“逐层交接”

数据解封装看起来像一个底层细节,但它实际上决定了网络程序为什么会出现大量看似奇怪的问题。

例如,网页打不开时,不一定是浏览器问题。可能是网卡没有收到帧,可能是路由错误,也可能是 DNS、TCP 握手、TLS 证书或 HTTP 服务端配置出了问题。

数据库连不上时,也不一定意味着数据库宕机。可能是端口没有监听,防火墙阻断了 TCP 包,服务器路由配置错误,或者程序连接到了错误的 IP 地址。

理解解封装之后,排查网络问题会更有层次。

可以按从底到上的顺序思考:

网卡是否正常接收数据? 二层 MAC 地址是否正确? IP 地址和路由是否可达? TCP / UDP 端口是否开放? 程序是否监听该端口? 应用层协议是否正常?

例如,在 Linux 或 Windows 上排查网络问题时,经常会用到不同层次的工具。

查看本机 IP、网关和 DNS,可以使用:

ipconfig /all

或:

ipaddriproute

测试目标主机是否可达,可以使用:

ping目标IP

测试某个端口是否开放,可以使用:

telnet IP 端口

或者:

curl-vhttps://example.com

查看本机监听端口,可以使用:

netstat-ano

或者:

ss-lntp

如果需要进一步观察真实的网络报文,可以使用 Wireshark 或 tcpdump。它们能让你直接看到以太网帧、IP 头、TCP 标志位、HTTP 请求头甚至部分应用层内容。

当你在 Wireshark 中看到:

Ethernet II Internet Protocol Version 4 Transmission Control Protocol Hypertext Transfer Protocol

其实就是在亲眼观察一条数据逐层被解析和解封装的过程。

网络通信并不是简单的“程序 A 把文字发送给程序 B”。它是多个协议层依次完成身份确认、路径判断、可靠传输和业务解释的结果。

网卡负责把数据从物理世界接进来;IP 层负责确认数据属于谁、该往哪里走;TCP 或 UDP 负责把数据送到正确端口;应用程序最终理解这些字节真正代表什么。

浏览器看到一张网页,微信显示一条消息,数据库返回一行记录,看起来都很简单。但背后其实是一场极其精密的逐层交接。

http://www.gsyq.cn/news/1590570.html

相关文章:

  • 对话聊天(Chatbot)
  • LangGraph图编排底层原理:状态、节点与边的工程实践
  • 从零构建异构高性能计算集群:Kubernetes与Ceph实战指南
  • 近期碎片0625
  • ChatGPT嵌入DAM系统:自然语言驱动数字资产智能操作
  • 一个传统企业老板的自白
  • Linux命令-pwconv(从 /etc/passwd 创建 /etc/shadow 影子密码)
  • FRSM V6 Dense MoE vs Transformer — 全维度技术报告
  • 智能工程师中的方案设计与优化分析
  • 告别招人内卷!零基础用 QClaw,一人撑起整盘生意
  • 偏函数与柯里化:函数式编程技巧
  • Kubernetes 生产集群故障自愈:从 Pod 驱逐到节点自动恢复的实战进阶
  • 斐波那契常数数字分布分析:从高精度计算到统计检验
  • 【微科普】一文吃透GDPR与CCPA数据法规,后端隐私接口改造附完整方案
  • 程序员专属浪漫!自制HTML生日蛋糕粒子特效源码
  • 照片总修不出“通透感“?这款AI修图神器,一键让废片变大片!
  • 国产开源神器!一个U盘装N个系统,拷贝ISO就能启动,再也不用反复格式化!
  • 2026实测盘点:16款降AI率工具测评,论文安全过关就靠它!
  • ML 实验管理工具链调研:Weights Biases、MLflow 与 DVC 的架构对比与选型评估
  • Mapper算法标签置换零模型的统计收敛性证明与工程实践
  • 智慧军营部队人员车辆信息化管理系统建设方案
  • HarmonyOS 6.1.0 Weather Service 智慧出行与天气服务怎么设计?
  • Python 进阶技巧:异步迭代器与生成器管道——高并发数据流处理的工程范式
  • Pearcleaner:深度解析macOS应用清理的现代Swift架构实现
  • 多协议转换:用 Go 标准库手写 gRPC 翻译网关
  • Linux CPU利用率深度解析:从top命令到虚拟化资源评估
  • Ryujinx模拟器完整配置指南:从零开始畅玩Switch游戏
  • AI 情感陪伴进阶:从情绪识别到共情响应的工程化实现
  • 模型训练进阶:学习率调度与预热策略——从震荡崩溃到稳定收敛的调参实录
  • Prometheus黑盒监控实践:用Blackbox Exporter检测网站与网络可用性