Linux網(wǎng)絡傳輸全流程:從局域網(wǎng)通信到跨網(wǎng)絡路由,拆解傳輸?shù)牡暮诵臋C制
前言:
做 Linux C/C++ 后端開發(fā)的同學,幾乎每天都在和網(wǎng)絡打交道:寫 Socket 服務、調 HTTP 接口、排查線上網(wǎng)絡超時 / 丟包問題,但很多人都停留在「調用 API 實現(xiàn)功能」的層面,卻從未深究過一個最核心的問題:當我們在代碼里調用send()發(fā)送一句 “你好”,這句數(shù)據(jù)到底經(jīng)歷了什么,才能從本機的應用程序,跨越網(wǎng)線、交換機、路由器,最終精準地出現(xiàn)在另一臺主機的應用程序里?很多網(wǎng)絡編程的坑、線上疑難故障,本質都是對底層傳輸流程的理解缺失導致的。本文就從局域網(wǎng)通信的底層原理出發(fā),一步步拆解 TCP/IP 協(xié)議棧的數(shù)據(jù)封裝與解包全流程,再到跨網(wǎng)絡傳輸?shù)穆酚蛇壿嫞Y合 Linux 內核源碼,把網(wǎng)絡傳輸?shù)牡讓舆壿嬛v得明明白白。
一. 前置故事和知識點鋪墊

故事:網(wǎng)絡購物,快遞單的例子
快遞小哥送快遞給我肯定不會直接把商品拿出來給我,而是快遞單,快遞單是給快遞公司和快遞小哥看的,送到我手上之后,我才會拆開快遞把東西拿出來。
我實際收到的東西比期望的多,因為多了一個快遞盒子和快遞單
我們這里的快遞單子其實就是報頭,盒子是封裝,內容叫做有效載荷,其中盒子沒有單獨的數(shù)據(jù)結構。
- 快遞單:報頭; --> 協(xié)議的體現(xiàn)
- 快遞盒:封裝;
- 盒子里裝的內容(商品):有效載荷。

任何一個中轉的站點都認識這些快遞單上的字段— 這就是約定,協(xié)議。未來收到數(shù)據(jù),基本都要包含兩部分:報頭 + 數(shù)據(jù)(有效載荷)
我在意的是里面的東西,但是實際會有多的東西,就是報頭,這個報頭也就是雙方都認識的結構體變量。


二. 網(wǎng)絡傳輸?shù)暮诵幕篗AC 地址與 IP 地址
網(wǎng)絡通信的本質,是「數(shù)據(jù)從一個主機的進程,精準送達另一個主機的進程」。而要實現(xiàn)這個目標,首先需要兩個核心標識,分別解決「局域網(wǎng)內找誰」和「全網(wǎng)范圍內找誰」的問題。
2.1 MAC 地址:局域網(wǎng)內的設備身份證(附以太網(wǎng)的核心通信規(guī)則)
MAC 地址(Media Access Control Address,媒體訪問控制地址),是數(shù)據(jù)鏈路層的核心概念,用來標識局域網(wǎng)內相連的節(jié)點。

核心特性
- 長度與格式:固定為48 比特位(6 個字節(jié)),通常用 16 進制數(shù)字 + 冒號的形式表示,例如
08:00:27:03:fb:19。 - 唯一性:在網(wǎng)卡出廠時就燒錄到硬件中,理論上全球唯一,不可修改(虛擬機的 MAC 地址為虛擬地址,可能存在沖突;部分網(wǎng)卡支持軟件配置 MAC 地址)。
- 作用范圍:僅在局域網(wǎng)內有效,核心作用是實現(xiàn)局域網(wǎng)內相鄰設備的精準尋址。

查看方式
Windows 系統(tǒng):在 cmd 中執(zhí)行
ipconfig /all,即可看到網(wǎng)卡的物理地址(MAC 地址);
Linux 系統(tǒng):執(zhí)行
ifconfig或ip addr,ether字段后即為 MAC 地址。

以太網(wǎng)的核心通信規(guī)則
以太網(wǎng)有一個剛性要求:任何時刻,只允許一臺主機在局域網(wǎng)中發(fā)送數(shù)據(jù)。
如果多臺主機同時發(fā)送數(shù)據(jù),光電信號會產(chǎn)生干擾,我們稱之為數(shù)據(jù)碰撞,碰撞后的數(shù)據(jù)會變成無效的垃圾數(shù)據(jù)。因此以太網(wǎng)中的所有主機,都必須實現(xiàn)碰撞檢測與碰撞避免機制:
- 發(fā)送數(shù)據(jù)前先監(jiān)聽信道是否空閑,空閑才發(fā)送;
- 發(fā)送過程中持續(xù)檢測是否發(fā)生碰撞,檢測到碰撞后立即停止發(fā)送,等待隨機時間后重試;
- 沒有交換機的情況下,一個以太網(wǎng)就是一個完整的碰撞域。

2.2 IP 地址:互聯(lián)網(wǎng)中的主機門牌號
IP 地址是 IP 協(xié)議中用來標識網(wǎng)絡中不同主機的地址,是網(wǎng)絡層的核心概念,我們日常學習默認以IPv4為主。
核心特性
- 長度與格式:IPv4 地址是一個4 字節(jié)(32 位)的整數(shù),通常用「點分十進制」的字符串表示,例如192.168.0.1,用點分割的每個數(shù)字代表一個字節(jié),取值范圍 0-255。
- 唯一性:在公網(wǎng)范圍內,IP 地址唯一標識一臺主機;局域網(wǎng)內可通過私有 IP 段實現(xiàn)內網(wǎng)唯一標識。
- 核心作用:全網(wǎng)地址管理與路由選擇,是數(shù)據(jù)從源主機到目標主機的路徑規(guī)劃核心依據(jù)。屏蔽底層網(wǎng)絡差異


IP地址,一個“數(shù)字”怎么能夠幫我們進行路徑選擇和主機定位的問題!
比如我們在學校里面的學號,別人可以通過學號找到一個人嘛,是可以的,學號都是有規(guī)律的,多少位代表學院,多少位代表班級,多少位代表宿舍…,那么在網(wǎng)絡當中能通過IP地址找到目標主機也沒啥好意外的了。
IP地址也分源IP地址和目標IP地址,后面我們再說,通過學號能找到對應的人的本質其實是學校做了一系列基礎工作的結果。所以理解IP地址我們還應該重點去研究運營商是如何做基礎建設的。

2.3 MAC 地址與 IP 地址的核心區(qū)別
這是網(wǎng)絡學習最核心的基礎,也是面試高頻考點,我們用表格和通俗類比徹底講透:
| 特性 | MAC 地址 | IP 地址 |
|---|---|---|
| 所屬層級 | 數(shù)據(jù)鏈路層 | 網(wǎng)絡層 |
| 核心作用 | 局域網(wǎng)內相鄰設備的精準尋址 | 全網(wǎng)范圍內的主機標識與路由規(guī)劃 |
| 長度與格式 | 6 字節(jié) 48 位,十六進制冒號分隔 | 4 字節(jié) 32 位,點分十進制 |
| 可變性 | 出廠固定,理論不可修改 | 可手動 / 動態(tài)配置,隨網(wǎng)絡環(huán)境變化 |
| 傳輸過程中的變化 | 每經(jīng)過一次路由轉發(fā),源 / 目標 MAC 地址都會更新 | 整個端到端傳輸過程中,源 / 目標 IP 地址始終不變 |
通俗類比:
- 目標 IP 地址 = 快遞的最終收件地址「XX 省 XX 市 XX 小區(qū) XX 室」,是整個傳輸?shù)淖罱K目標,全程不會改變;
- 目標 MAC 地址 = 快遞的下一站轉運中心地址,每到一個轉運中心就會更新,只負責當前一段路程的精準送達。
IP 地址是路徑選擇的核心依據(jù),MAC 地址是局域網(wǎng)內逐跳轉發(fā)的核心依據(jù),二者協(xié)同完成了數(shù)據(jù)從源主機到目標主機的完整傳輸。
三. 概念補充:認知上的轉變(以太網(wǎng) && MAC地址)
3.1 更換視角:你是如何看待局域網(wǎng)(以太網(wǎng))
以太網(wǎng) 本身就是共享資源 ,在任意一個時刻,共享資源只能別被一臺主機使用,每臺主機就是一個我們剛剛做的工作,不就是在處理 互斥與同步 問題嘛。但是加鎖感覺不重。還有一種就是令牌環(huán)網(wǎng)
這是局域網(wǎng)歷史上最著名的兩套“規(guī)則”。如果說 以太網(wǎng)(Ethernet)是大家在一個房間里自由發(fā)言(誰行誰上,撞了就停),那么 令牌環(huán)網(wǎng)(Token Ring) 就是大家圍成一圈坐好,手里拿著麥克風(令牌)的人才能說話。
作為研究 Linux 內核和系統(tǒng)編程的你,理解這兩者的區(qū)別不僅是網(wǎng)絡基礎,更是理解 介質訪問控制(MAC) 邏輯的好機會。
這個所謂的令牌環(huán)網(wǎng)(也是臨界資源),不就是我們之前的鎖(令牌)嘛
從內核與底層開發(fā)的視角來看
- 驅動處理:在 Linux 內核中,以太網(wǎng)驅動(
net/ethernet)處理的是極其異步的任務。而令牌環(huán)網(wǎng)(內核代碼中仍有net/802/tr.c等痕跡,雖然已過時)則需要嚴格的定時器和狀態(tài)機來管理令牌。 - 確定性需求:雖然以太網(wǎng)贏了商用市場,但在一些實時工業(yè)控制領域(如 EtherCAT 或某些車載協(xié)議),依然能看到“令牌”或者“時間片分發(fā)”思想的影子,因為這些領域需要像令牌環(huán)網(wǎng)那樣的“確定性延遲”。
總結:以太網(wǎng)靠著“大道至簡”和交換機技術的引入(消滅了物理沖突域),打敗了結構嚴謹?shù)恐氐牧钆骗h(huán)網(wǎng)。
- 補充擴展:測試抗壓能力

3.2 以太網(wǎng)為什么叫做以太網(wǎng)

3.3 重新回歸MAC地址的概念(補充強化)
網(wǎng)絡通信的一般“動力”是用戶!因為用戶在頂層。自頂向下,貫穿協(xié)議棧
數(shù)據(jù)鏈路層在最底層。網(wǎng)卡本質是外設,要把數(shù)據(jù)搬到內存自底向上,交付給用戶
要發(fā)送數(shù)據(jù),用戶交付到下一層,每一層都要有一個協(xié)議,交付的時候都要添加自己的報頭
大家還記得我們的快遞單例子嘛!我實際收到的會比我期望的多一點,多的就是快遞單也就是報頭。
封裝:就是把結構體變量拷貝到前面
這個過程是自頂向下封裝的過程


3.4 概念回顧(統(tǒng)一精準化表達)
統(tǒng)一精準化表述名詞:
- 在應用層把報文(報頭 + 有效載荷)叫做 請求與應答
- 在傳輸層把報文叫做數(shù)據(jù)段
- 在網(wǎng)絡層把報文叫做數(shù)據(jù)報
- 在鏈路層把報文叫做數(shù)據(jù)幀

下三層屬于內核:傳輸,網(wǎng)絡,鏈路
邏輯上認為是兩臺主機在直接通信;物理上不是,中間的過程有挺多的。
網(wǎng)絡里面收到數(shù)據(jù)一定是硬件先收到,也就是網(wǎng)卡。網(wǎng)卡一旦收到了數(shù)據(jù)幀,中斷觸發(fā),報告CPU(CPU會知道中斷號等),而OS一定能做到把數(shù)據(jù)從外設搬到內存(這個是體系結構支持的)
四. 局域網(wǎng)通信的完整流程:封裝與解包
兩臺主機在同一個局域網(wǎng)內的通信,是網(wǎng)絡傳輸?shù)幕A,整個過程的核心就是數(shù)據(jù)的封裝(發(fā)送端)與解包 + 分用(接收端)。
4.1 基礎夯實:先搞懂 3 個核心概念
我們用生活中「寄快遞」的例子,就能徹底理解這三個概念,這是整個傳輸流程的基石:
- 報文 = 報頭 + 有效載荷
- 有效載荷:你真正要寄的商品,也就是業(yè)務需要傳遞的核心數(shù)據(jù)(比如 “你好” 這句話);
- 報頭:快遞面單,是每層協(xié)議添加的控制信息,包含「目標地址、源地址、上層協(xié)議類型、數(shù)據(jù)長度」等關鍵信息;
- 報文:快遞包裹(面單 + 商品),也就是每層協(xié)議最終傳遞的數(shù)據(jù)單元。
- 不同層級的報文有專屬名稱
- 傳輸層:數(shù)據(jù)單元叫做段(segment),比如 TCP 段、UDP 段;
- 網(wǎng)絡層:數(shù)據(jù)單元叫做數(shù)據(jù)報(datagram),比如 IP 數(shù)據(jù)報;
- 數(shù)據(jù)鏈路層:數(shù)據(jù)單元叫做幀(frame),比如以太網(wǎng)幀。
- 封裝與解包
- 封裝:發(fā)送數(shù)據(jù)時,數(shù)據(jù)自頂向下(應用層→物理層),每經(jīng)過一層協(xié)議,就添加該層的協(xié)議報頭,最終形成以太網(wǎng)幀發(fā)送到物理介質的過程;
- 解包:接收數(shù)據(jù)時,數(shù)據(jù)自底向上(物理層→應用層),每經(jīng)過一層協(xié)議,就剝掉對應層的報頭,根據(jù)報頭信息將數(shù)據(jù)交付給上層協(xié)議的過程;
- 分用:解包過程中,根據(jù)報頭中的「上層協(xié)議字段」,將數(shù)據(jù)精準交付給對應上層協(xié)議處理的過程,是解包的核心環(huán)節(jié)。

4.2 發(fā)送端:數(shù)據(jù)封裝的完整過程
我們以主機 A 向同一局域網(wǎng)的主機 B 發(fā)送 “你好” 為例,拆解自頂向下的完整封裝流程,每一步都對應 TCP/IP 五層模型的核心操作。

第一步:應用層封裝
主機 A 的聊天應用生成業(yè)務數(shù)據(jù) “你好”,應用層協(xié)議(如自定義聊天協(xié)議、HTTP 協(xié)議)會給數(shù)據(jù)添加應用層報頭,形成應用層報文,傳遞給傳輸層。
應用層報頭包含業(yè)務相關的控制信息,比如消息類型、發(fā)送人 ID、消息長度等,由開發(fā)者自定義或遵循標準應用層協(xié)議。
第二步:傳輸層封裝
傳輸層(TCP/UDP)收到應用層報文后,添加TCP/UDP 報頭,形成傳輸層段,傳遞給網(wǎng)絡層。
我們以 Linux 內核中 TCP 報頭的結構體為例,深度解析報頭的核心內容:
// Linux內核中TCP協(xié)議報頭的結構體定義
struct tcphdr
{
__be16 source; // 16位源端口號:標識發(fā)送端進程
__be16 dest; // 16位目的端口號:標識接收端進程
__be32 seq; // 32位序列號:保證數(shù)據(jù)按序傳輸
__be32 ack_seq; // 32位確認序列號:實現(xiàn)可靠傳輸?shù)拇_認應答
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u16 res1:4, // 保留位
doff:4, // 數(shù)據(jù)偏移:TCP報頭長度
fin:1, // 關閉連接標志
syn:1, // 建立連接標志
rst:1, // 重置連接標志
psh:1, // 推送標志
ack:1, // 確認標志
urg:1, // 緊急指針標志
ece:1, // 擁塞通知標志
cwr:1; // 擁塞窗口縮減標志
#elif defined(__BIG_ENDIAN_BITFIELD)
__u16 doff:4,
res1:4,
cwr:1,
ece:1,
urg:1,
ack:1,
psh:1,
rst:1,
syn:1,
fin:1;
#endif
__be16 window; // 16位窗口大?。簩崿F(xiàn)流量控制
__sum16 check; // 16位校驗和:校驗數(shù)據(jù)是否損壞
__be16 urg_ptr; // 16位緊急指針:標識緊急數(shù)據(jù)的位置
};
逐行核心解析:
source和dest:核心分用字段,16 位端口號唯一標識主機內的進程,是數(shù)據(jù)最終能送達對應應用程序的關鍵;seq和ack_seq:TCP 可靠傳輸?shù)暮诵?,通過序列號和確認號保證數(shù)據(jù)不丟失、不亂序;- 標志位(
fin/syn/ack等):TCP 連接管理、狀態(tài)控制的核心; window:實現(xiàn)流量控制,告訴對方自己的接收能力,避免數(shù)據(jù)溢出;check:校驗和,接收端通過此字段判斷數(shù)據(jù)在傳輸過程中是否損壞。
第三步:網(wǎng)絡層封裝
網(wǎng)絡層(IP 協(xié)議)收到傳輸層段后,添加IP 報頭,形成 IP 數(shù)據(jù)報,傳遞給數(shù)據(jù)鏈路層。
同樣我們看 Linux 內核中 IP 協(xié)議報頭的結構體:
// Linux內核中IPv4協(xié)議報頭的結構體定義
struct iphdr
{
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u8 version:4, // 4位版本號:IPv4填4,IPv6填6
ihl:4; // 4位首部長度:IP報頭的長度
#elif defined(__BIG_ENDIAN_BITFIELD)
__u8 ihl:4,
version:4;
#endif
__u8 tos; // 8位服務類型:定義數(shù)據(jù)的優(yōu)先級、QoS特性
__be16 tot_len; // 16位總長度:IP數(shù)據(jù)報的總長度(報頭+載荷)
__be16 id; // 16位標識:唯一標識每個IP數(shù)據(jù)報,用于分片重組
__be16 frag_off; // 16位分片偏移:標識分片在原始報文中的位置
__u8 ttl; // 8位生存時間:數(shù)據(jù)報的最大跳數(shù),每經(jīng)過一個路由器減1
__u8 protocol; // 8位上層協(xié)議號:標識載荷交給哪個上層協(xié)議(6=TCP,17=UDP)
__sum16 check; // 16位首部校驗和:校驗IP報頭是否損壞
__be32 saddr; // 32位源IP地址:發(fā)送端主機IP
__be32 daddr; // 32位目的IP地址:接收端主機IP
};
逐行核心解析:
version和ihl:標識 IP 協(xié)議版本和報頭長度,是解析 IP 數(shù)據(jù)報的基礎;saddr和daddr:核心路由字段,源 IP 和目標 IP 全程不變,是端到端傳輸?shù)暮诵臉俗R;protocol:核心分用字段,告訴網(wǎng)絡層收到的數(shù)據(jù)應該交給傳輸層的 TCP 還是 UDP 協(xié)議;ttl:避免數(shù)據(jù)報在網(wǎng)絡中無限循環(huán),是網(wǎng)絡防環(huán)的核心機制tot_len、id、frag_off:實現(xiàn) IP 數(shù)據(jù)報的分片與重組,適配不同鏈路層的最大傳輸單元(MTU)。
第四步:數(shù)據(jù)鏈路層封裝
數(shù)據(jù)鏈路層(以太網(wǎng)協(xié)議)收到 IP 數(shù)據(jù)報后,添加以太網(wǎng)幀頭和幀尾,形成完整的以太網(wǎng)幀,傳遞給物理層。
- 以太網(wǎng)幀的核心結構:
| 字段 | 長度(字節(jié)) |
|---|---|
| 目的 MAC 地址 | 6 |
| 源 MAC 地址 | 6 |
| 類型 / 長度 | 2 |
| 數(shù)據(jù) | 46-1500 |
| 幀校驗序列 FCS | 4 |
核心字段解析:
- 目的 / 源 MAC 地址:6 字節(jié),局域網(wǎng)內尋址的核心,接收端通過目的 MAC 地址判斷報文是否發(fā)給自己;
- 類型字段:2 字節(jié),核心分用字段,標識數(shù)據(jù)字段的上層協(xié)議(0x0800=IP 協(xié)議,0x0806=ARP 協(xié)議);
- 數(shù)據(jù)字段:46-1500 字節(jié),承載上層的 IP 數(shù)據(jù)報,也就是網(wǎng)絡層交付的有效載荷;
- FCS 幀尾:4 字節(jié),循環(huán)冗余校驗,用于檢測數(shù)據(jù)在傳輸過程中是否出現(xiàn)錯誤。
第五步:物理層發(fā)送
物理層收到以太網(wǎng)幀后,將二進制數(shù)據(jù)轉換成光電信號,通過網(wǎng)線、WiFi 等物理介質,發(fā)送到局域網(wǎng)中。


4.3 局域網(wǎng)內的報文廣播與接收
以太網(wǎng)是廣播型網(wǎng)絡,主機 A 發(fā)送的以太網(wǎng)幀,會被發(fā)送到局域網(wǎng)內的所有主機。
每臺主機的網(wǎng)卡收到報文后,會首先檢查以太網(wǎng)幀頭中的目的 MAC 地址:
- 如果目的 MAC 地址和本機網(wǎng)卡的 MAC 地址不匹配,直接將報文丟棄,上層完全無感知;
- 如果目的 MAC 地址和本機 MAC 地址匹配,就將以太網(wǎng)幀交給內核的數(shù)據(jù)鏈路層處理,進入解包分用流程。
4.4 接收端:數(shù)據(jù)解包與分用的完整過程
主機 B 收到匹配 MAC 地址的以太網(wǎng)幀后,開始自底向上的解包與分用,整個過程和封裝完全相反,核心是 「逐層剝頭、精準分用」。

第一步:數(shù)據(jù)鏈路層解包分用
數(shù)據(jù)鏈路層剝掉以太網(wǎng)幀頭和幀尾,根據(jù)幀頭中的類型字段判斷上層協(xié)議:
- 如果類型字段是 0x0800,說明載荷是 IP 數(shù)據(jù)報,將數(shù)據(jù)交付給網(wǎng)絡層的 IP 協(xié)議;
- 如果類型字段是 0x0806,說明載荷是 ARP 報文,將數(shù)據(jù)交付給 ARP 協(xié)議處理。
第二步:網(wǎng)絡層解包分用
網(wǎng)絡層剝掉 IP 報頭,首先校驗 IP 報頭的校驗和,確認報頭無損壞,然后檢查目標 IP 地址是否為本機 IP:
- 校驗不通過或 IP 不匹配,直接丟棄報文;
- 校驗通過且 IP 匹配,根據(jù) IP 報頭中的protocol 字段判斷上層協(xié)議:
- 字段值為 6,說明載荷是 TCP 段,交付給傳輸層的 TCP 協(xié)議;
- 字段值為 17,說明載荷是 UDP 段,交付給傳輸層的 UDP 協(xié)議。
第三步:傳輸層解包分用
傳輸層剝掉 TCP/UDP 報頭,校驗和確認數(shù)據(jù)無損壞,然后根據(jù)報頭中的目的端口號,找到本機中監(jiān)聽該端口的應用進程,將最終的應用層數(shù)據(jù)交付給對應的進程。
第四步:應用層處理
應用程序收到傳輸層交付的 “你好” 數(shù)據(jù),完成一次完整的局域網(wǎng)通信。
核心認知:在邏輯上,我們認為「同層協(xié)議之間在直接通信」。比如主機 A 的 TCP 層,認為自己在和主機 B 的 TCP 層直接對話;主機 A 的 IP 層,認為自己在和主機 B 的 IP 層直接對話。盡管物理上數(shù)據(jù)必須經(jīng)過層層封裝解包,但協(xié)議的分層設計,屏蔽了底層的傳輸細節(jié),讓每層只需要關注自己的核心職責。



4.5 深度理解協(xié)議棧(圖示說明)

4.6 Linux 內核中封裝的底層實現(xiàn)
在 Linux 內核中,所有網(wǎng)絡數(shù)據(jù)包的管理,都基于核心結構體sk_buff(Socket Buffer),封裝的本質就是對sk_buff的指針操作,而非內存拷貝,這也是內核高性能網(wǎng)絡處理的核心。
我們用內核偽代碼看封裝的核心邏輯:
// 內核封裝IP報頭的核心偽代碼 struct sk_buff *skb; // 內核中的數(shù)據(jù)包管理結構體 struct iphdr *iph; // 1. 指針前移,預留IP報頭的空間,skb_push返回新的指針位置 iph = (struct iphdr *)skb_push(skb, sizeof(struct iphdr)); // 2. 填充IP報頭的各個字段,也就是填寫"快遞面單" iph->version = 4; // IPv4協(xié)議 iph->ihl = 5; // 報頭長度20字節(jié) iph->tos = 0; // 普通服務類型 iph->tot_len = htons(skb->len); // 總長度,轉換為網(wǎng)絡字節(jié)序 iph->id = htons(atomic_inc_return(&ip_id_counter)); // 唯一標識 iph->frag_off = 0; // 不分片 iph->ttl = 64; // 默認生存時間64跳 iph->protocol = IPPROTO_TCP; // 上層協(xié)議為TCP iph->saddr = source_ip; // 源IP地址 iph->daddr = dest_ip; // 目標IP地址 iph->check = 0; // 先清零,后續(xù)計算校驗和 iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); // 計算校驗和
代碼核心解析:
skb_push:內核中最核心的封裝操作,將數(shù)據(jù)包的頭部指針向低地址方向移動,預留出對應協(xié)議報頭的空間,全程無需內存拷貝,性能極高;- 填充報頭字段:本質就是給協(xié)議結構體的成員變量賦值,也就是我們說的「填寫快遞面單」;
- 字節(jié)序轉換:所有超過 1 字節(jié)的字段(如 tot_len、id),都必須通過
htons/htonl轉換為大端格式的網(wǎng)絡字節(jié)序,保證不同架構的主機都能正確解析; - 校驗和計算:用于接收端校驗數(shù)據(jù)完整性,是網(wǎng)絡傳輸可靠性的基礎保障。
解包的操作則完全相反,通過skb_pull將指針向高地址方向移動,剝掉對應層的報頭,再根據(jù)報頭字段進行分用處理。
五. 跨網(wǎng)絡傳輸?shù)暮诵牧鞒蹋郝酚膳c逐跳轉發(fā)
5.1 路由器的核心作用
路由器是工作在網(wǎng)絡層的設備,核心能力有兩個:
- 路由選擇:通過路由表,為 IP 數(shù)據(jù)報規(guī)劃從源主機到目標主機的最優(yōu)傳輸路徑;
- 分組轉發(fā):將收到的 IP 數(shù)據(jù)報,根據(jù)路由表轉發(fā)到下一跳的正確地址。
簡單來說,路由器就是互聯(lián)網(wǎng)中的「快遞轉運中心」,負責把數(shù)據(jù)從一個局域網(wǎng),轉發(fā)到另一個局域網(wǎng),最終送達目標主機所在的網(wǎng)絡。
5.2 跨網(wǎng)絡傳輸?shù)耐暾鞒?/h3>
我們以源主機 A(IP:192.168.2.2,MAC:MacA),向跨網(wǎng)段的目標主機 B(IP:172.168.2.2,MAC:MacB)發(fā)送數(shù)據(jù)為例,拆解完整的跨網(wǎng)傳輸流程,核心是「IP 地址全程不變,MAC 地址逐跳更新」。

第一步:源主機判斷目標網(wǎng)段,確定下一跳
主機 A 的網(wǎng)絡層通過子網(wǎng)掩碼判斷,目標 IP172.168.2.2 和本機不在同一個局域網(wǎng),因此會將數(shù)據(jù)轉發(fā)給默認網(wǎng)關(路由器)。
主機 A 通過 ARP 協(xié)議獲取網(wǎng)關的 MAC 地址 MacLeft,然后進行封裝:
- IP 報頭:源 IP=192.168.2.2,目標 IP=172.168.2.2(全程不變);
- 以太網(wǎng)幀頭:源 MAC=MacA,目標 MAC=MacLeft(路由器的入站口 MAC)。
第二步:路由器接收數(shù)據(jù),解包與路由查詢
路由器收到以太網(wǎng)幀后,進行解包:
- 數(shù)據(jù)鏈路層剝掉幀頭,根據(jù)類型字段將 IP 數(shù)據(jù)報交付給網(wǎng)絡層;
- 網(wǎng)絡層檢查 IP 報頭的目標 IP 地址,查詢本地路由表,找到到達 172.168.2.0 網(wǎng)段的下一跳地址,確定出站口;
- 路由器將 IP 報頭中的 TTL 字段減 1,如果 TTL 變?yōu)?0,直接丟棄報文,避免循環(huán)轉發(fā)。
第三步:路由器重新封裝,轉發(fā)數(shù)據(jù)
路由器確定下一跳后,重新進行數(shù)據(jù)鏈路層封裝:
- IP 報頭:源 IP 和目標 IP 完全不變,僅修改 TTL 字段;
- 以太網(wǎng)幀頭:源 MAC=MacRight(路由器的出站口 MAC),目標 MAC=MacB(目標主機 B 的 MAC 地址)。
封裝完成后,將新的以太網(wǎng)幀發(fā)送到目標主機 B 所在的局域網(wǎng)。
第四步:目標主機接收數(shù)據(jù),解包分用
主機 B 收到以太網(wǎng)幀后,檢查目標 MAC 地址匹配,開始自底向上的解包分用,最終將數(shù)據(jù)交付給對應的應用進程,完成跨網(wǎng)絡通信。
關鍵細節(jié):如果跨網(wǎng)傳輸需要經(jīng)過多個路由器,那么每經(jīng)過一個路由器,都會重復「解包→路由查詢→重新封裝」的過程,源 / 目標 IP 全程不變,而源 / 目標 MAC 地址會在每一跳都更新為當前路段的入站 / 出站 MAC 地址。

5.3 IP 網(wǎng)絡層的核心意義 && 網(wǎng)絡通信的宏觀流程
IP 網(wǎng)絡層的存在,為整個互聯(lián)網(wǎng)提供了統(tǒng)一的網(wǎng)絡虛擬層,它完美屏蔽了底層不同網(wǎng)絡的硬件差異:無論是以太網(wǎng)、令牌環(huán)網(wǎng)、光纖網(wǎng)絡,還是 WiFi 無線網(wǎng)絡,無論底層的物理介質和數(shù)據(jù)鏈路層協(xié)議有多大差異,只要都實現(xiàn)了 IP 協(xié)議,就能實現(xiàn)互聯(lián)互通。
這就是互聯(lián)網(wǎng)能夠連接全球數(shù)十億設備的核心底層邏輯:IP 協(xié)議統(tǒng)一了全網(wǎng)的通信標準,而路由技術實現(xiàn)了數(shù)據(jù)在全球范圍內的精準轉發(fā)。


六. 核心考點總結(面試高頻)
- MAC 地址和 IP 地址的區(qū)別:所屬層級、核心作用、傳輸過程中的變化,以及二者的通俗類比;
- 數(shù)據(jù)封裝與解包的完整流程:TCP/IP 五層模型中,每一層封裝添加的報頭核心字段,以及解包分用的核心依據(jù);
- 以太網(wǎng)幀的核心結構:目的 / 源 MAC 地址、類型字段的作用,MTU 的含義;
- TCP 報頭和 IP 報頭的核心字段:端口號、序列號、確認號、源 / 目標 IP、協(xié)議號、TTL 等字段的作用;
- 局域網(wǎng)通信的原理:CSMA/CD 機制、碰撞域的概念、廣播與接收的判斷邏輯;
- 跨網(wǎng)絡傳輸?shù)牧鞒?/strong>:路由器的作用、逐跳轉發(fā)的過程、IP 與 MAC 地址在路由過程中的變化;
- 分用的核心邏輯:以太網(wǎng)類型字段、IP 協(xié)議號、TCP/UDP 端口號在分用過程中的作用;
- Linux 內核
sk_buff的核心作用:skb_push/skb_pull在封裝解包中的意義。
結尾
網(wǎng)絡傳輸?shù)牡讓舆壿?,看似復雜,實則核心就是「封裝與解包」兩個動作,以及「MAC 地址負責局域網(wǎng)內逐跳轉發(fā),IP 地址負責全網(wǎng)路由規(guī)劃」兩個核心原則。對于 Linux 后端開發(fā)者來說,理解這整套傳輸流程,絕不僅僅是為了應付面試。當你線上遇到 TCP 握手失敗、數(shù)據(jù)丟包、跨網(wǎng)訪問超時等問題時,只有吃透了底層傳輸原理,才能精準定位問題出在哪一層、哪個環(huán)節(jié);當你開發(fā)高性能網(wǎng)絡服務時,也只有理解了內核的數(shù)據(jù)包處理流程,才能寫出更高效的代碼,做更精準的性能優(yōu)化。網(wǎng)絡編程的上限,永遠取決于你對底層原理的理解深度。
到此這篇關于Linux網(wǎng)絡傳輸全流程:從局域網(wǎng)通信到跨網(wǎng)絡路由,拆解傳輸?shù)牡暮诵臋C制的文章就介紹到這了,更多相關Linux C/C++后端開發(fā)中網(wǎng)絡傳輸?shù)牡讓釉韮热菡埶阉髂_本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Linux平臺和Windows平臺互傳文件的實現(xiàn)方法
本文講述了在Linux主機與windows主機之間如何互傳文件的方法,因為有時linux主機中的一些文件可能會在windows環(huán)境下用到,所以文章給大家介紹的非常詳細,感興趣的朋友可以參考下2024-05-05
Linux系統(tǒng)中查看當前文件夾下文件的個數(shù)實現(xiàn)方式
本文介紹了在Linux系統(tǒng)中使用ls命令查看文件數(shù)量的方法,包括顯示指定目錄下的內容、統(tǒng)計文件數(shù)量等并查看當前路徑下文件夾的個數(shù),同時介紹了使用wc-l、ls及amp;ldquo;-l&rdrdquo;和grep命令的用法,并對這些命令進行了總結和應用2026-05-05
Ubuntu文件系統(tǒng)磁盤空間不足報錯low disk space on file
最近開始啟動Ubuntu20.04時提示的信息如下:Low Disk Space on “Filesystem root”,這是因為Ubuntu文件系統(tǒng)磁盤空間不足導致的,所以本文給大家詳細介紹了Ubuntu文件系統(tǒng)磁盤空間不足報錯low disk space on filesystem root的解決方案,需要的朋友可以參考下2024-09-09
Apache Iceberg 底層數(shù)據(jù)查詢原理解析
Apache Iceberg是一個開源表格格式,用于大型分析數(shù)據(jù)集,本文主要介紹了如何通過快照、Manifest文件和元數(shù)據(jù)文件查詢Iceberg表的數(shù)據(jù),通過解析元數(shù)據(jù)文件獲取當前表的快照ID,進而讀取對應的Avro文件和Manifest文件中的Parquet數(shù)據(jù)文件,感興趣的朋友一起看看吧2024-09-09
CentOS 5.1下跑Mono和Asp.net的實現(xiàn)方法
由于想研究在linux下跑.net程序的可行性,于是嘗試在CentOS5.1下搭建Mono環(huán)境和Asp.Net的服務器。Asp.Net的服務器是采用mod_mono和Apache的方式搭建(Nginx的搭建尚未研究)。2010-04-04

