網路與 IP

UDP 和 TCP 的區別:對照表、首部長度與連接埠選型

UDP 和 TCP 都是傳輸層協議,區別在於可靠性由誰負責:TCP 先握手建立連線,按序號確認、丟了重傳、按網路狀況調速,首部至少 20 位元組;UDP 不建連線、不確認、不調速,首部固定 8 位元組,可靠性交給應用自己處理。放行連接埠、壓測和排查丟包時,兩者的做法和要看的指標都不一樣。

作者 頂聯產品團隊發布於 7 分鐘閱讀

UDP 和 TCP 是 TCP/IP 傳輸層的兩個協議,IP 協議號分別是 17 和 6。TCP(傳輸控制協議)面向連線:先三次握手,再按序號傳送,對方逐段確認,丟了就重傳,並且按接收方的處理能力和網路擁塞程度調節速度,交給應用的是一條不丟、不亂、不重的位元組流。UDP(使用者資料包協議)無連線:應用交給它一個報文,它就發出一個資料包,不確認、不重傳、不調速。代價和收益都寫在首部裡:TCP 首部最少 20 位元組,UDP 只有 8 位元組。業務用哪個協議通常由開發者決定,維運要做的是弄清每個服務走哪個協議,放行連接埠、壓測、排查丟包時不要用錯方法。

TCP 和 UDP 的區別對照表

對比項 TCP UDP 對維運的影響
IP 協議號 6 17 防火牆和 ACL 靠它區分,-p tcp 與 -p udp 是兩條規則
連線 三次握手建立,四次揮手關閉 沒有連線,第一個包就是資料 TCP 建連多一個往返;UDP 連接埠沒有握手可以用來驗證“通不通”
可靠性 序號、確認、超時重傳,保證不丟、不亂序、不重複 不保證,丟失、亂序、重複都原樣交給應用 TCP 丟包表現為變慢;UDP 丟包表現為資料缺失:卡頓、破圖、查詢超時
流量控制 接收視窗:接收方來不及處理時讓傳送方暫停 沒有,接收緩衝區滿了就丟 UDP 服務要盯接收緩衝區溢位計數
擁塞控制 有,Linux 預設 CUBIC,可選 BBR 沒有,應用發多快就多快 多條 TCP 流會自動分享頻寬;UDP 洪流會擠佔同一出口上的 TCP
資料形式 位元組流,沒有訊息邊界 資料包,發一次對應收一次 TCP 應用要自己切分訊息
首部長度 20–60 位元組 固定 8 位元組 小包業務裡差別明顯,見下一節
單包載荷(IPv4,MTU 1500) MSS 1460 位元組,帶時間戳選項時 1448 不分片最多 1472 位元組 UDP 一次發得更大,就會觸發 IP 分片
通訊方式 只能一對一 一對一、廣播、組播 DHCP 靠廣播,組播直播只能用 UDP
狀態 兩端都維護連線狀態和收發緩衝區 協議本身沒有狀態 狀態防火牆對 UDP 只能按超時判斷“會話”是否結束

一句話概括:TCP 把可靠性做在協議裡,UDP 把可靠性留給應用。所以 UDP 不是“差一點的 TCP”,而是一個更薄的底座:DNS 在它上面做超時重查,QUIC 在它上面重新實現了一整套可靠傳輸。

首部長度:TCP 20 位元組、UDP 8 位元組差在哪

兩個首部都以源連接埠、目的連接埠開頭,差別全在 TCP 多出來的那些欄位,每個欄位對應一項能力:

欄位 TCP UDP 用來做什麼
源連接埠、目的連接埠 各 16 位 各 16 位 區分同一台主機上的程式
序號 32 位 無 給每個位元組編號,用來排序和去重
確認號 32 位 無 告訴對方“這之前的都收到了”
首部長度 4 位,單位是 4 位元組 無;另有 16 位長度欄位,含首部和資料 TCP 首部可變長,靠它找到資料從哪開始,最大 15 × 4 = 60 位元組
標誌位 SYN、ACK、FIN、RST、PSH、URG 等 無 建立、確認、關閉、復位連線
視窗 16 位 無 流量控制:本端還能接收多少位元組
校驗和 16 位,必須計算 16 位,IPv4 下可以填 0 發現傳輸差錯
緊急指標 16 位 無 很少使用
選項 0–40 位元組 無 MSS、視窗擴大、SACK、時間戳

加起來,TCP 固定部分是 2 + 2 + 4 + 4 + 2 + 2 + 2 + 2 = 20 位元組,UDP 是 2 + 2 + 2 + 2 = 8 位元組。

這 12 位元組的差距在不同業務裡分量完全不同。假設一個遊戲每次同步 100 位元組的狀態:走 UDP,IP 包是 20 + 8 + 100 = 128 位元組;走 TCP,Linux 預設帶時間戳選項,TCP 首部 32 位元組,IP 包是 20 + 32 + 100 = 152 位元組,多了約 19%,而且對方還要回 ACK(Linux 會延遲確認、把幾個包合併成一次),每個純 ACK 又是一個 52 位元組的 IP 包。傳大檔案時正好相反:1500 位元組的滿載包裡 TCP 首部只佔 2% 左右,首部長短幾乎不影響吞吐,起作用的是重傳和擁塞控制。

常見服務各走哪個協議

服務 預設連接埠 協議 說明
SSH、FTP 控制連線、SMTP、HTTP 22、21、25、80 只用 TCP —
BGP 179 只用 TCP 路由器之間的會話
MySQL、Redis 3306、6379 只用 TCP —
DHCP 67、68 只用 UDP 客戶端還沒有位址,只能靠廣播
TFTP、NTP、SNMP 69、123、161 與 162 UDP SNMP 規範上也能走 TCP,裝置實際基本只用 UDP
IPMI(RMCP+) 623 只用 UDP —
VXLAN、WireGuard 4789、常用 51820 只用 UDP 隧道封裝
DNS 53 兩種都用 查詢多走 UDP;應答太大和區域傳送走 TCP
HTTPS 443 兩種都用 HTTP/1.1、HTTP/2 走 TCP,HTTP/3 走 UDP
RDP 3389 兩種都用 TCP 建立會話,較新的客戶端和伺服器再加一條 UDP 傳畫面
iperf3 5201 兩種都用 控制連線始終走 TCP,UDP 測試的資料走 UDP
OpenVPN 1194 二選一 預設 UDP,可改為 TCP,以服務端配置的 proto 為準
Syslog 514 二選一 傳統上用 UDP,rsyslog 等也支援 TCP,連接埠以配置為準
Minecraft Java 版、基岩版 25565、19132 TCP、UDP 同一款遊戲,兩個版本用的協議不同

最容易出問題的是“兩種都用”的幾項。業務方說“開一下 443”,要追問是否啟用了 HTTP/3;只放行 TCP 443 時網站照樣能開啟,只是瀏覽器退回 HTTP/2,問題不會暴露,但 HTTP/3 的效果也就沒有了。“二選一”的服務,以服務端配置檔案裡寫的為準,例如 OpenVPN 看 proto udp 還是 proto tcp。

放行連接埠時:先確認服務監聽的是哪個協議

一個典型工單:客戶在伺服器上搭了 Minecraft 基岩版,安全組裡放行了 19132,玩家還是連不上。查下來是安全組規則選成了 TCP,而基岩版用的是 UDP。這類問題按三步排除:

  1. 在伺服器上看服務實際監聽的協議。 ss -tulnp 同時列出 TCP 和 UDP,第一列 Netid 就是協議;UDP 沒有連線,狀態顯示為 UNCONN 而不是 LISTEN:
ss -tulnp | grep -E ':(22|19132) '
udp   UNCONN 0      0            0.0.0.0:19132      0.0.0.0:*    users:(("bedrock_server",pid=2817,fd=9))
tcp   LISTEN 0      128          0.0.0.0:22         0.0.0.0:*    users:(("sshd",pid=812,fd=3))
  1. 按協議放行,連接埠號相同也要分開寫。 安全組規則和系統防火牆都要帶上協議,19132/tcp 放行了,19132/udp 仍然是關著的:
firewall-cmd --permanent --add-port=19132/udp && firewall-cmd --reload   # firewalld
ufw allow 19132/udp                                                       # ufw
  1. 驗證時別拿 TCP 的辦法測 UDP。 nc -zv -w 3 203.0.113.10 22 對 TCP 連接埠有明確結論:成功、被拒絕或超時。換成 nc -zuv 測 UDP 連接埠,只要沒收到 ICMP 連接埠不可達,它多半也報告成功,這個結果不能作數;以伺服器上 tcpdump -nni any udp port 19132 能否看到玩家的請求為準。

壓測:iperf3 測 TCP 和測 UDP,看的指標不同

同一條鏈路,用 iperf3 分別測 TCP 和 UDP,回答的是兩個不同的問題:

# TCP:一條受擁塞控制的連線(或 -P 指定多條)最多能跑多快
iperf3 -c 203.0.113.10 -t 30 -P 4
# UDP:按指定速率傳送,對端收到多少、丟了多少、抖動多大
iperf3 -c 203.0.113.10 -u -b 300M -t 30

TCP 測試遇到丟包會自己降速,結果是一個“被丟包和延遲壓低之後的速度”,丟包本身只體現在 Retr(重傳段數)一列;UDP 測試不管網路狀況,按 -b 指定的速率一直髮,結果直接給出丟包比例(Lost/Total Datagrams)和抖動(Jitter)。iperf3 的 UDP 測試預設只發 1 Mbit/s,必須用 -b 指定速率;對端的防火牆要同時放行 TCP 5201 和 UDP 5201。

兩種結果合起來看:

TCP 結果 UDP 結果(同等速率) 判斷
跑滿簽約頻寬 丟包接近 0 鏈路正常
跑不滿,Retr 很多 較低速率下就有持續丟包 鏈路本身在丟包(線路、光模組、擁塞),TCP 是被丟包拖慢的
跑不滿,Retr 很少 不丟包 瓶頸在視窗或延遲,不在丟包;加大併發連線數或調大緩衝區再測
— 超過某個速率後丟包陡增 碰到了限速或連接埠上限,這個速率就是實際可用頻寬
— 丟包,同時對端 UdpRcvbufErrors 同步增長 包丟在接收端主機內部,不是線路問題

UDP 壓測還有一個注意事項:它不會因為擁塞而讓步。在生產出口上跑不設上限的 UDP 測試,會把同一出口上所有 TCP 業務一起擠慢,壓測應放在低峰並控制速率和時長。

排查丟包:TCP 看重傳,UDP 看接收端計數

同樣 1% 的丟包,落在兩種協議上的表現不同,查的地方也不同。

TCP:丟包變成重傳和降速。 業務表現是慢,而不是資料錯。看單條連線用 ss -ti,輸出裡的 retrans:0/37 表示這條連線累計重傳了 37 次,rtt:35.2/1.1 是平滑後的往返時間和它的波動(毫秒);看整機用 nstat -az TcpRetransSegs TcpOutSegs,間隔一段時間取兩次差值,重傳段數除以傳送段數就是重傳率。

ss -ti dst 203.0.113.10

UDP:協議層沒有重傳,丟了就沒了。 業務表現是語音斷續、畫面破圖、DNS 偶發超時。先排除主機自己丟的:

nstat -az UdpInDatagrams UdpInErrors UdpRcvbufErrors UdpNoPorts
計數器 增長說明
UdpRcvbufErrors 接收緩衝區滿了,程式讀得不夠快,要調大緩衝區或最佳化程式
UdpNoPorts 資料包發到了沒有程式監聽的連接埠,核心回了 ICMP 連接埠不可達;服務沒起來或連接埠配錯
UdpInErrors 接收出錯的總數,包含緩衝區溢位和校驗和錯誤

主機計數正常,再查路上。這時要注意探測協議要和業務一致:ping 和 mtr 預設用 ICMP,有些網路對 ICMP、UDP 的處理與 TCP 不同,常見於跨境鏈路和帶防護策略的線路,會對某類流量限速或降低轉發優先順序。用 ICMP 測出來不丟包,不代表 UDP 業務也不丟。mtr 可以直接改用業務協議探測:

mtr -n -r -c 200 -T -P 443 203.0.113.10    # TCP SYN 探測 443 連接埠
mtr -n -r -c 200 -u -P 53 203.0.113.10     # UDP 探測

讀結果時看最後一跳:中間某一跳顯示丟包、後面各跳都不丟,通常是那台路由器對探測包的回應做了限速,不是真的丟包。

在機房裡怎麼落地

兩種協議對機房的另一個區別是“會不會讓路”。TCP 有擁塞控制,出口緊張時各條連線會自動降速;UDP 沒有,一台伺服器被利用做反射放大的跳板,或者客戶跑起了不限速的 UDP 業務,流量會一直頂在連接埠上限,擠佔同一上聯的其他客戶。Toplink DCIM 的頻寬自動限速取一段時間視窗內的平均頻寬做判斷,入方向和出方向各有自己的閾值,超標就把交換器連接埠壓到設定的速率,流量回落並保持到設定的時長後自動恢復原速率,對這類不會自己降速的流量很有用。限速、連接埠開關這些動作由交換器管理按廠商指令集下發到交換器,不用值班人員逐台登入。伺服器上開放了哪些 TCP、UDP 連接埠,仍要在系統防火牆和安全組裡按協議逐條收緊。

常見問題

TCP 一定比 UDP 慢嗎?

不一定。鏈路乾淨時,TCP 同樣能跑滿頻寬,它的“慢”主要體現在建連多一個往返、丟包後要等重傳和降速。對延遲敏感、又能容忍少量資料丟失的業務,UDP 的優勢才明顯。

為什麼 VPN 隧道大多用 UDP 承載?

隧道里跑的多半是 TCP 連線,它們自己會重傳。外層再用 TCP 的話,一旦丟包,內外兩層同時重傳、同時降速,吞吐會急劇下降。所以 WireGuard 只用 UDP,OpenVPN 預設也是 UDP,TCP 模式一般只在 UDP 被封鎖時備用。

UDP 能做到可靠傳輸嗎?

能,但要由應用自己實現。QUIC 在 UDP 之上實現了確認、重傳和擁塞控制,HTTP/3 就跑在它上面;TFTP 每傳一塊等一次確認;DNS 靠客戶端超時重查。

想看看在你的機房裡怎麼用?

從一次產品示範開始,梳理你的業務鏈路。

查看價格
服務熱線 400-112-2951

讓我們聊聊你的 IDC 業務

掃碼新增企業微信,預約產品示範或申請試用。

Toplink 企業微信二維碼

長按儲存或使用企業微信 / 微信掃描

也可致電
400-112-2951
Telegram
@TopLink88