UDP 和 TCP 的區別:對照表、首部長度與連接埠選型
UDP 和 TCP 都是傳輸層協議,區別在於可靠性由誰負責:TCP 先握手建立連線,按序號確認、丟了重傳、按網路狀況調速,首部至少 20 位元組;UDP 不建連線、不確認、不調速,首部固定 8 位元組,可靠性交給應用自己處理。放行連接埠、壓測和排查丟包時,兩者的做法和要看的指標都不一樣。
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。這類問題按三步排除:
- 在伺服器上看服務實際監聽的協議。
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))
- 按協議放行,連接埠號相同也要分開寫。 安全組規則和系統防火牆都要帶上協議,19132/tcp 放行了,19132/udp 仍然是關著的:
firewall-cmd --permanent --add-port=19132/udp && firewall-cmd --reload # firewalld
ufw allow 19132/udp # ufw
- 驗證時別拿 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 靠客戶端超時重查。