目前仅存储有关 DataChannel 的信息
在进行 WebRTC 通信时,节点间会按照如下顺序获取对方的地址:
- 如果双端在同一个内网,直接用内网IP通信;
- 通过
STUN
服务器,为双端构造可以直接访问的地址,打造一条可以穿透 NAT 的通路,俗称“打洞”; - 双端通过
TURN
服务器(中继服务器)进行通信。此时,通信网络的拓扑结构不再是P2P
,因为数据其实是经过 TURN 服务器转发给双端的。
理想情况下,连接双方都是公网 IP,可以直接进行点对点连接。但是大部分情况下都不是这样的,需要一个信令服务来交换双方的网络信息,并通过 ICE 服务(STUN 协议)来打洞实现点对点链接。
大概的流程是
// 1. 创建一个 PeerConnection
const peerConnection = new RTCPeerConnection({
// stun/turn 服务,用于打洞
iceServers: [
{
urls: "stun:stun3.l.google.com:19302",
},
],
});
// 设置 icecandidate (这一步是交换网络信息)
senderPeerConnection.onicecandidate = (e) =>
!e.candidate ||
receiverPeerConnection
.addIceCandidate(e.candidate)
.catch(handleAddCandidateError);
receiverPeerConnection.onicecandidate = (e) =>
!e.candidate ||
senderPeerConnection
.addIceCandidate(e.candidate)
.catch(handleAddCandidateError);
// 2. 如果需要点对点连接,双方需要发起申请并应答
const offer = await senderPeerConnection.createOffer();
// 创建完 offer 应立刻设置,offer 需要通过信令服务传输
senderPeerConnection.setLocalDescription(offer);
// 接收方拿到 offer 设置 remoteDescription
// 并创建 answer 给 sender
receiverPeerConnection.setRemoteDescription(offer);
const answer = await receiverPeerConnection.createAnswer();
receiverPeerConnection.setLocalDescription(answer);
// sender 拿到 answer 并设置
senderPeerConnection.setRemoteDescription(data);
由此双方可建立联系
// sender
const senderChannel = senderPeerConnection.createDataChannel("desc"));
// receiver
receiverPeerConnection.ondatachannel = (data) => {
const receiverChannel = data.channel
}
事件
channel.onopen = () => { }
channel.onmessage = () => { }
用 Docker
docker run -d -p 3478:3478 -p 3478:3478/udp -p 5349:5349 -p 5349:5349/udp -p 49152-65535:49152-65535/udp coturn/coturn
注意: port range
越大启动的速度越慢,可以稍微减少一些
Or just use the host network directly (recommended, as Docker performs badly with large port ranges):
docker run -d --network=host coturn/coturn
docker-compose.yaml
version: '3'
services:
coturn:
image: coturn/coturn
container_name: coturn_server
network_mode: host
restart: unless-stopped