跳至主要內容
Skip to content

WebRTC 實戰 (4) —— ICE Candidate 與 NAT 穿越

如果你跟著前三篇實作,你可能會發現:在同一個 Wi-Fi 下連線沒問題,但一旦一台用 4G,一台用公司 Wi-Fi,連線就建立不起來。

這是因為我們還沒解決網路世界中最頑固的障礙:NAT (網路位址轉換)防火牆


一、 根本問題:為什麼 P2P 很難?

在現代網路中,大部分的設備都沒有公網 IP。你的設備可能處於一個私有網路中 (如 192.168.x.x)。當 A 想連線給 B 時,A 只知道 B 的私有 IP,但這在公網上是無法路由的。


二、 救援三劍客:STUN, TURN, ICE

1. STUN (Session Traversal Utilities for NAT)

功能:告訴設備它的「公網 IP」是什麼。伺服器負擔輕,流量不經過它,速度快。

2. TURN (Traversal Using Relays around NAT)

功能:中繼轉發。當 P2P 真的連不上的時候,影音流量會全部經過 TURN 伺服器轉發。保證 100% 連通,但延遲較高。

3. ICE (Interactive Connectivity Establishment)

功能:負責收集所有的連線可能性(稱為 ICE Candidates),並挑選出一條最優的路徑。


三、 前端實作:處理 ICE 事件

你需要在 RTCPeerConnection 建立後,立即監聽 onicecandidate 事件:

javascript
/* 前端代碼 */
const pc = new RTCPeerConnection({
  iceServers: [
    { urls: "stun:stun.l.google.com:19302" },
    { urls: "turn:your-turn-server.com", username: "u", credential: "p" },
  ],
});

pc.onicecandidate = (event) => {
  if (event.candidate) {
    signaling.send({
      type: "candidate",
      candidate: event.candidate,
      to: "Target_User",
    });
  }
};

signaling.onMessage = async (msg) => {
  if (msg.type === "candidate") {
    await pc.addIceCandidate(new RTCIceCandidate(msg.candidate));
  }
};

總結

今天我們解開了 WebRTC 連線最痛苦的一環:NAT 穿透與 ICE Candidate 交換邏輯。至此,你已經完整掌握了底層原理實戰的所有連線流程。

下一篇,我們將介紹一個常被忽略的強大武器:Data Channel。


️ 進階挑戰

打開 Chrome 瀏覽器並輸入 chrome://webrtc-internals/。在進行 WebRTC 連線時觀察 IceCandidatePair 的狀態變遷。你能分辨出目前正在使用的連線路徑是 host (內網)、srflx (STUN/公網) 還是 relay (TURN/中繼) 嗎?


延伸閱讀與資源

← 上一章:SDP 交換與媒體協商 | 返回專案首頁 | 下一章:Data Channel