WebRTC 實戰 (5) —— Data Channel:不只是傳影音
很多人誤以為 WebRTC 只能用來視訊或通話。其實,它還提供了 RTCDataChannel,允許你在兩台電腦之間建立一個 低延遲、高吞吐量 的資料通道。
一、 核心概念:SCTP 傳輸
Data Channel 建立在 SCTP (Stream Control Transmission Protocol) 之上:
- 可靠且有序:預設模式,資料會重傳並保持順序,適合聊天與檔案控制訊息。
- 部分可靠或無序:可設定
maxRetransmits、maxPacketLifeTime或ordered: false,適合允許丟失的即時狀態。
二、 實作:建立數據通道
Data Channel 的建立必須依附於 RTCPeerConnection,且通常是在 Offer 發起端建立。
1. 發起端 (Offerer)
javascript
const pc = new RTCPeerConnection();
const dc = pc.createDataChannel("chat-room", {
ordered: true,
});
dc.onopen = () => {
console.log("通道已開啟!");
dc.send("Hello WebRTC!");
};
dc.onmessage = (event) => console.log("收到訊息:", event.data);send() 只能在 readyState === "open" 時呼叫。若要使用部分可靠傳輸,可另外建立通道:
javascript
const positionChannel = pc.createDataChannel("position", {
ordered: false,
maxRetransmits: 0,
});2. 接收端 (Answerer)
接收端監聽 ondatachannel 事件:
javascript
pc.ondatachannel = (event) => {
const receiveChannel = event.channel;
receiveChannel.onopen = () => console.log("接收通道已開啟");
receiveChannel.onmessage = (e) => console.log("接收端收到:", e.data);
};3. 大檔案需要背壓控制
檔案不能一次塞進 DataChannel。應切成較小區塊,並監控 bufferedAmount,避免瀏覽器持續累積待送資料:
javascript
dc.bufferedAmountLowThreshold = 256 * 1024;
async function waitForBuffer() {
if (dc.bufferedAmount <= dc.bufferedAmountLowThreshold) return;
await new Promise((resolve) => {
dc.addEventListener("bufferedamountlow", resolve, { once: true });
});
}三、 應用場景
- 即時通訊:在已建立 PeerConnection 的使用者之間傳送聊天資料,減少應用伺服器的資料轉送量。
- 多人遊戲:利用「非可靠傳輸」同步玩家座標,獲得極低延遲。
- P2P 檔案共享:直接路徑成功時不需應用伺服器中轉;若 ICE 選到 Relay Candidate,資料仍會經過 TURN。
總結
今天我們解鎖了 WebRTC 的半壁江山:RTCDataChannel。它可以平衡可靠性與速度,是開發高性能 P2P 應用的關鍵。
下一篇,我們將進入第二階段:討論如何利用成熟的框架 PeerJS 來優化這一切。
進階挑戰
試著實作一個「P2P 檔案傳輸進度條」。你需要發送方定期發送「目前已發送 Chunk 數量」的資訊,而接收方則根據總檔案大小更新 UI。別忘了在傳送完畢後,正確合併所有的 ArrayBuffer 並觸發下載!
延伸閱讀與資源
- MDN: RTCDataChannel API
- WebRTC Samples: Transmit text and files