TCP 與 UDP:傳輸層協定深入解析 | Networking

2026/05/09

TCPUDP 是傳輸層(Transport Layer)最核心的兩個協定。TCP 提供可靠、有序、連接導向的資料傳輸,適用於網頁瀏覽、檔案傳輸等場景;UDP 則以無連接、低延遲的方式快速傳送資料,適合即時語音、線上遊戲等應用。本文從 封包結構三向交握流量控制壅塞控制Socket 程式設計診斷指令,完整解析兩大傳輸層協定的運作原理與實務應用。

傳輸層在網路模型中的角色

傳輸層(Transport Layer)位於 OSI 模型的第四層,介於應用層與網路層之間,負責端對端(End-to-End)的資料傳輸。應用程式透過傳輸層將資料交給底層網路傳送,而傳輸層則透過 端口號(Port Number) 來區分同一主機上的不同應用程式。

┌─────────────────────────────────┐
│  應用層(Application Layer)     │  HTTP, FTP, DNS, SMTP, SSH
├─────────────────────────────────┤
│  傳輸層(Transport Layer)       │  ← TCP / UDP 在此層
├─────────────────────────────────┤
│  網路層(Network Layer)         │  IP, ICMP, ARP
├─────────────────────────────────┤
│  資料鏈結層(Data Link Layer)   │  Ethernet, Wi-Fi
├─────────────────────────────────┤
│  實體層(Physical Layer)        │  電纜、光纖、無線電波
└─────────────────────────────────┘

端口號的範圍從 0 到 65535,分為三個區段:

範圍名稱說明
0 – 1023Well-known Ports系統保留,需 root 權限(HTTP 80、HTTPS 443、SSH 22)
1024 – 49151Registered PortsIANA 註冊的應用程式端口(MySQL 3306、Redis 6379)
49152 – 65535Dynamic / Ephemeral Ports客戶端臨時使用,由作業系統自動分配

TCP 協定總覽

傳輸控制協定(Transmission Control Protocol,TCP)是一種 連接導向(Connection-oriented) 的傳輸層協定,提供可靠、有序的位元組串流傳輸。在開始傳送資料之前,TCP 必須先透過三向交握(Three-way Handshake)建立連線,確保通訊雙方準備就緒。

TCP 的核心特性:

  • 可靠傳輸(Reliable):透過序號、確認應答、重傳機制保證資料完整到達
  • 有序傳輸(Ordered):接收端按序號重組資料,保證順序正確
  • 流量控制(Flow Control):滑動窗口機制防止發送方淹沒接收方
  • 壅塞控制(Congestion Control):偵測網路壅塞並動態調整傳輸速率
  • 全雙工(Full-duplex):雙方可同時傳送與接收資料

TCP 標頭結構

TCP 標頭的基本大小為 20 bytes,加上可選項(Options)最多可達 60 bytes。以下是標頭的主要欄位:

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|          Source Port          |       Destination Port        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                        Sequence Number                        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                    Acknowledgment Number                      |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|  Data |       |C|E|U|A|P|R|S|F|                               |
| Offset| Rsrvd |W|C|R|C|S|S|Y|I|            Window             |
|       |       |R|E|G|K|H|T|N|N|                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|           Checksum            |         Urgent Pointer        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
欄位大小說明
Source Port16 bits來源端口號
Destination Port16 bits目的端口號
Sequence Number32 bits資料位元組的序號,用於排序與重組
Acknowledgment Number32 bits期望接收的下一個位元組序號
Data Offset4 bits標頭長度(以 4 bytes 為單位)
Flags9 bits控制旗標:SYN、ACK、FIN、RST、PSH、URG 等
Window16 bits接收窗口大小,用於流量控制
Checksum16 bits標頭與資料的校驗和

其中 Flags 旗標欄位是 TCP 連線管理的關鍵:

旗標全名用途
SYNSynchronize建立連線,同步初始序號
ACKAcknowledgment確認收到資料
FINFinish請求關閉連線
RSTReset強制重置連線
PSHPush要求立即將資料推送給應用層
URGUrgent標記緊急資料

TCP 三向交握(Three-way Handshake)

TCP 連線建立需要三次握手,目的是同步雙方的初始序號(Initial Sequence Number,ISN)並確認雙方均準備好通訊。

    客戶端 (Client)                     伺服器 (Server)
        │                                    │
        │  ① SYN (seq=x)                    │
        │ ──────────────────────────────────→│
        │    客戶端進入 SYN_SENT 狀態          │  伺服器進入 SYN_RCVD 狀態
        │                                    │
        │  ② SYN-ACK (seq=y, ack=x+1)       │
        │←────────────────────────────────── │
        │                                    │
        │  ③ ACK (seq=x+1, ack=y+1)         │
        │ ──────────────────────────────────→│
        │    連線建立(ESTABLISHED)           │  連線建立(ESTABLISHED)
        │                                    │

詳細流程:

  1. SYN:客戶端發送 SYN 封包,攜帶隨機初始序號 x,進入 SYN_SENT 狀態
  2. SYN-ACK:伺服器回應 SYN+ACK,攜帶自己的初始序號 y,確認號為 x+1,進入 SYN_RCVD 狀態
  3. ACK:客戶端回覆 ACK,確認號為 y+1,雙方進入 ESTABLISHED 狀態

為什麼需要三次而非兩次? 三次握手確保雙方都能確認對方的接收與發送能力。若只有兩次,伺服器無法確認客戶端已收到 SYN-ACK,可能導致半開連線(Half-open Connection),白白浪費伺服器資源。


TCP 四次揮手(Four-way Termination)

TCP 是全雙工協定,每個方向的資料傳輸需要獨立關閉,因此連線關閉需要四次揮手。

    客戶端 (Client)                     伺服器 (Server)
        │                                    │
        │  ① FIN (seq=u)                    │
        │ ──────────────────────────────────→│
        │    FIN_WAIT_1                       │  CLOSE_WAIT
        │                                    │
        │  ② ACK (ack=u+1)                  │
        │←────────────────────────────────── │
        │    FIN_WAIT_2                       │  (伺服器可能還有資料要傳送)
        │                                    │
        │  ③ FIN (seq=v)                     │
        │←────────────────────────────────── │
        │    TIME_WAIT                        │  LAST_ACK
        │                                    │
        │  ④ ACK (ack=v+1)                  │
        │ ──────────────────────────────────→│
        │    等待 2×MSL 後關閉                │  CLOSED
        │    CLOSED                           │
        │                                    │

流程說明:

  1. FIN:主動關閉方發送 FIN,表示「我不再發送資料了」
  2. ACK:被動關閉方確認收到 FIN,但此時可能還有資料尚未傳送完畢
  3. FIN:被動關閉方傳完剩餘資料後,也發送 FIN
  4. ACK:主動關閉方確認,進入 TIME_WAIT 狀態,等待 2 x MSL(Maximum Segment Lifetime,通常 60 秒)後關閉

TIME_WAIT 的意義: 確保最後的 ACK 能到達對方(若遺失,對方會重傳 FIN),同時讓網路中殘留的舊封包自然消亡,避免影響後續新連線。


TCP 滑動窗口與流量控制

滑動窗口(Sliding Window)是 TCP 流量控制的核心機制,允許發送方在未收到確認的情況下連續發送多個封包,大幅提升傳輸效率。

發送方的資料緩衝區:

已確認    ┃ 可發送(窗口內)    ┃ 不可發送(窗口外)
──────────┃───────────────────┃────────────────────
  1 2 3 4 ┃ 5 6 7 8 9 10 11  ┃ 12 13 14 15 ...
          ↑                   ↑
      窗口左邊界           窗口右邊界

運作方式:

  • 接收方在 ACK 中通告 Window Size,表示自己剩餘的緩衝區空間
  • 基本窗口最大為 65,535 bytes(16 bits),透過 Window Scale 選項可擴展至 1 GB
  • 當接收方緩衝區滿時,通告窗口大小為 0,發送方暫停傳送
  • 接收方處理完資料後,發送 Window Update 通知發送方繼續

這個機制確保快速的發送方不會淹沒較慢的接收方,實現端對端的流量調節。


TCP 壅塞控制

壅塞控制(Congestion Control)與流量控制不同——流量控制防止發送方淹沒「接收方」,壅塞控制則防止發送方淹沒「網路」。TCP 使用壅塞窗口(Congestion Window,cwnd)來動態調整傳輸速率。

cwnd (壅塞窗口大小)
  │
  │            ╱ 壅塞避免(線性增加)
  │          ╱
  │        ╱ ← ssthresh(慢啟動閾值)
  │      ╱
  │    ╱  慢啟動(指數增加)
  │  ╱
  │╱
  └──────────────────────────── 時間
         ↑
      發生壅塞 → cwnd 減半或重置
演算法觸發條件行為
慢啟動(Slow Start)連線初始或超時後cwnd 從 1 MSS 開始,每收到一個 ACK 翻倍(指數增長)
壅塞避免(Congestion Avoidance)cwnd >= ssthreshcwnd 每個 RTT 增加 1 MSS(線性增長)
快速重傳(Fast Retransmit)收到 3 個重複 ACK不等超時,立即重傳遺失的封包
快速恢復(Fast Recovery)快速重傳後ssthresh = cwnd/2,cwnd = ssthresh + 3 MSS

常見的壅塞控制演算法包括經典的 Reno(AIMD 策略)、Linux 預設的 Cubic(三次方函數控制窗口增長),以及 Google 開發的 BBR(基於頻寬與延遲模型)。


UDP 協定總覽

使用者資料報協定(User Datagram Protocol,UDP)是一種 無連接(Connectionless) 的傳輸層協定。與 TCP 不同,UDP 不需要建立連線、不保證資料到達、也不保證順序——它只負責把資料盡快送出去。

UDP 的核心特性:

  • 無連接:不需要握手,直接發送資料報(Datagram)
  • 不保證可靠性:封包可能遺失、亂序或重複,不提供重傳機制
  • 低延遲:沒有握手延遲、沒有壅塞控制延遲
  • 輕量標頭:僅 8 bytes,遠小於 TCP 的 20-60 bytes
  • 支援廣播與多播(Multicast):可一對多傳送
  • 訊息導向(Message-oriented):保留訊息邊界,一次 send 對應一次 recv

UDP 標頭結構

UDP 標頭結構極為簡潔,僅有 8 bytes:

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|          Source Port          |       Destination Port        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|            Length             |           Checksum            |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
欄位大小說明
Source Port16 bits來源端口號(可選,可設為 0)
Destination Port16 bits目的端口號
Length16 bitsUDP 封包總長度(標頭 + 資料),最小 8 bytes
Checksum16 bits校驗和(IPv4 可選,IPv6 必須)

對比 TCP 的 20+ bytes 標頭,UDP 的 8 bytes 標頭使其在傳輸小量資料時開銷更低、效率更高。


TCP vs UDP 完整比較

特性TCPUDP
連線方式連接導向(三向交握)無連接
可靠性保證到達、保證順序不保證
傳輸方式位元組串流(Byte Stream)訊息(Datagram)
標頭大小20-60 bytes8 bytes
流量控制有(滑動窗口)
壅塞控制有(Slow Start、AIMD 等)
傳輸速度較慢(有開銷)較快(低延遲)
廣播 / 多播不支援支援
訊息邊界不保留(串流)保留
適用場景可靠性優先速度 / 即時性優先

應用場景與常見協定對照

選擇 TCP 或 UDP 取決於應用對「可靠性」與「即時性」的需求。

使用 TCP 的場景

協定端口說明
HTTP / HTTPS80 / 443網頁傳輸,內容必須完整載入
FTP20 / 21檔案傳輸,檔案不可遺失
SSH22安全遠端登入,指令必須可靠傳送
SMTP25 / 587郵件發送
MySQL3306資料庫連線,SQL 查詢必須完整

使用 UDP 的場景

協定端口說明
DNS53域名解析查詢,單一小封包,快速回應
DHCP67 / 68動態 IP 分配
VoIP(SIP)5060語音通訊,低延遲比完整性重要
NTP123時間同步
線上遊戲動態遊戲狀態快速同步,舊資料不值得重傳
QUIC(HTTP/3)443在 UDP 上建構可靠傳輸,兼顧速度與可靠性

值得注意的是,DNS 是混合使用的代表:一般查詢使用 UDP(快速),但區域傳送(Zone Transfer)使用 TCP(確保完整性)。而 QUIC 協定則是在 UDP 之上實作了類似 TCP 的可靠性機制,代表了傳輸層技術的演進方向。


Socket 程式設計基礎

套接字(Socket)是應用程式存取傳輸層服務的 API 介面。一個 Socket 由 (IP 位址, 端口號, 協定) 唯一標識。以下以 Python 範例示範 TCP 與 UDP 的基本通訊。

TCP Socket 範例

# === TCP 伺服器端 (tcp_server.py) ===
import socket

# 建立 TCP Socket
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 綁定位址與端口
server.bind(('0.0.0.0', 8080))

# 開始監聽,最多排隊 5 個連線
server.listen(5)
print("TCP 伺服器啟動,等待連線...")

while True:
    # 接受客戶端連線(阻塞等待)
    client_socket, addr = server.accept()
    print(f"收到來自 {addr} 的連線")

    # 接收資料(最多 1024 bytes)
    data = client_socket.recv(1024)
    print(f"收到資料:{data.decode('utf-8')}")

    # 回傳回應
    client_socket.send("收到你的訊息!".encode('utf-8'))

    # 關閉連線
    client_socket.close()
# === TCP 客戶端 (tcp_client.py) ===
import socket

# 建立 TCP Socket
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 連線到伺服器(觸發三向交握)
client.connect(('127.0.0.1', 8080))

# 發送資料
client.send("Hello, TCP Server!".encode('utf-8'))

# 接收回應
response = client.recv(1024)
print(f"伺服器回應:{response.decode('utf-8')}")

# 關閉連線(觸發四次揮手)
client.close()

UDP Socket 範例

# === UDP 伺服器端 (udp_server.py) ===
import socket

# 建立 UDP Socket(注意使用 SOCK_DGRAM)
server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# 綁定位址與端口
server.bind(('0.0.0.0', 8081))
print("UDP 伺服器啟動,等待資料...")

while True:
    # 接收資料與來源位址(無需建立連線)
    data, addr = server.recvfrom(1024)
    print(f"收到來自 {addr} 的資料:{data.decode('utf-8')}")

    # 直接回傳給來源位址
    server.sendto("收到你的 UDP 訊息!".encode('utf-8'), addr)
# === UDP 客戶端 (udp_client.py) ===
import socket

# 建立 UDP Socket
client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# 直接發送資料(不需 connect,不需握手)
client.sendto("Hello, UDP Server!".encode('utf-8'), ('127.0.0.1', 8081))

# 接收回應
response, server_addr = client.recvfrom(1024)
print(f"伺服器回應:{response.decode('utf-8')}")

client.close()

從程式碼可以清楚看出兩者的差異:TCP 需要 connect / accept 建立連線,使用 send / recv 傳輸;UDP 直接使用 sendto / recvfrom,不需要連線建立的步驟。


實用診斷指令

掌握網路診斷工具能幫助你快速排查 TCP/UDP 相關問題。

ss 指令(Socket Statistics)

ss 是取代 netstat 的現代工具,速度更快、資訊更完整。

# 顯示所有 TCP 連線
ss -t -a

# 顯示處於 LISTENING 狀態的 TCP socket 及其端口號
ss -tln
# 輸出範例:
# State   Recv-Q  Send-Q  Local Address:Port  Peer Address:Port
# LISTEN  0       128     0.0.0.0:80          0.0.0.0:*

# 顯示 ESTABLISHED 狀態的 TCP 連線與對應的程序
ss -tnp state established
# 輸出範例:
# ESTAB  0  0  192.168.1.10:22  192.168.1.5:54321  users:(("sshd",pid=1234,fd=3))

# 篩選特定端口
ss -tlnp 'sport = :80 or sport = :443'

# 顯示所有 UDP 連線
ss -u -a

# 統計各狀態的 TCP 連線數
ss -s

netstat 指令(傳統工具)

# 顯示所有 TCP 連線
netstat -ant

# 顯示所有 UDP 連線
netstat -anu

# 顯示 LISTENING 及其 PID
netstat -tlnp

# 統計各狀態的 TCP 連線數量
netstat -ant | awk '{print $6}' | sort | uniq -c | sort -rn
# 輸出範例:
#      15 ESTABLISHED
#       3 TIME_WAIT
#       2 LISTEN
#       1 CLOSE_WAIT

tcpdump 封包擷取

tcpdump 是命令列封包分析工具,可以即時擷取並顯示網路封包內容。

# 擷取特定端口的 TCP 封包
sudo tcpdump -i eth0 tcp port 80 -nn

# 擷取 TCP 三向交握封包(SYN 或 ACK 旗標)
sudo tcpdump -i eth0 'tcp[tcpflags] & (tcp-syn|tcp-ack) != 0' -nn

# 只擷取 SYN 封包(觀察新連線建立)
sudo tcpdump -i eth0 'tcp[tcpflags] == tcp-syn' -nn

# 擷取 UDP DNS 查詢
sudo tcpdump -i eth0 udp port 53 -nn
# 輸出範例:
# 10:30:15.123456 IP 192.168.1.10.54321 > 8.8.8.8.53: UDP, length 42

# 將封包存入檔案供 Wireshark 分析
sudo tcpdump -i eth0 -w capture.pcap -c 1000

其他實用指令

# 檢查特定端口是否開啟
nc -zv 192.168.1.10 80
# 輸出範例:
# Connection to 192.168.1.10 80 port [tcp/http] succeeded!

# 查看系統目前使用的 TCP 壅塞控制演算法
cat /proc/sys/net/ipv4/tcp_congestion_control
# 輸出範例:cubic

# 查看 ephemeral port 範圍
cat /proc/sys/net/ipv4/ip_local_port_range
# 輸出範例:32768	60999

安全考量

TCP 和 UDP 在設計時並未將安全性作為首要考量,因此它們各自面臨不同的攻擊威脅。

TCP 常見攻擊

攻擊類型原理防禦方式
SYN Flood大量發送 SYN 封包但不完成三向交握,耗盡伺服器的半開連線佇列啟用 SYN Cookies、限制 SYN 速率、防火牆過濾
TCP Reset Attack偽造 RST 封包中斷合法連線使用 TLS 加密、TCP MD5 簽章
Session Hijacking猜測序號劫持已建立的連線隨機化初始序號(ISN)、強制使用 TLS

UDP 常見攻擊

攻擊類型原理防禦方式
UDP Flood大量 UDP 封包淹沒目標,消耗頻寬與處理能力速率限制、防火牆規則、DDoS 防護服務
DNS Amplification偽造來源 IP 發送 DNS 查詢,利用回應放大攻擊流量來源位址驗證(BCP38)、限制開放遞迴 DNS
NTP Amplification類似 DNS 放大,利用 NTP 的 monlist 指令產生大量回應停用 monlist、限制存取來源

由於 UDP 是無連接協定,偽造來源 IP 位址相對容易,因此 UDP 常被用作放大攻擊(Amplification Attack)的載體。在實務上,建議對外暴露的 UDP 服務務必搭配速率限制與存取控制。


總結

TCP 與 UDP 作為傳輸層的兩大支柱,各有其設計哲學與適用場景。TCP 透過三向交握、序號確認、滑動窗口、壅塞控制等機制,提供了完整的可靠傳輸保障,適合對資料完整性要求嚴格的應用(如網頁瀏覽、檔案傳輸、資料庫操作)。UDP 則以極簡的 8 bytes 標頭和無連接設計,換取最低的傳輸延遲,適合對即時性要求高但能容忍少量資料遺失的場景(如 VoIP、線上遊戲、DNS 查詢)。

在實際開發中,理解這兩個協定的運作原理,不僅有助於選擇合適的傳輸層協定,也能在遇到網路問題時,利用 sstcpdump 等工具快速定位問題。而隨著 QUIC(HTTP/3)等新協定的出現,傳輸層技術正朝著「在 UDP 上建構可靠性」的方向演進,值得持續關注。

更多網路基礎知識,請參考 IP、Subnet Mask、Gateway 完整教學