RTCPeerConnection API 详细介绍
RTCPeerConnection
是 WebRTC 中的核心对象,用于在两个客户端之间建立点对点连接。它管理音频、视频和数据的传输,并处理连接的建立、信令交换、ICE 候选者的协商等过程。
本文将详细介绍 RTCPeerConnection
的属性、方法和事件,并附带代码实例。
1. 构造函数
const peerConnection = new RTCPeerConnection(configuration);
参数:configuration
对象
RTCPeerConnection
的构造函数接受一个可选的 configuration
对象,用于配置 ICE(Interactive Connectivity Establishment)和 TURN/STUN 服务器。
configuration
对象的参数:
iceServers
: STUN 或 TURN 服务器的地址列表。用于帮助建立对等连接。iceTransportPolicy
: 控制 ICE 的策略,值可以为all
(默认)或relay
,决定是否只使用 TURN 服务器。bundlePolicy
: 定义如何在单个网络连接上传输媒体,值为balanced
(默认),max-compat
,max-bundle
。rtcpMuxPolicy
: 指定 RTP 和 RTCP 的多路复用策略,值为require
(默认)或negotiate
。iceCandidatePoolSize
: 设定 ICE 候选池的大小,默认是0
。
configuration
示例:
{
"iceServers": [
{ "urls": "stun:stun.l.google.com:19302" },
{
"urls": "turn:turn.example.com",
"username": "user",
"credential": "pass"
}
],
"iceTransportPolicy": "all",
"bundlePolicy": "balanced",
"rtcpMuxPolicy": "require",
"iceCandidatePoolSize": 10
}
2. 属性
2.1 connectionState
表示当前的连接状态,可能的值有:
new
: 初始状态,尚未建立连接。connecting
: 正在尝试建立连接。connected
: 已建立连接并且可以传输数据。disconnected
: 暂时断开,可能会恢复连接。failed
: 连接失败,无法恢复。closed
: 连接已被关闭。
示例:
console.log(peerConnection.connectionState); // "new"
2.2 iceConnectionState
表示 ICE 连接状态,包括以下值:
new
: ICE 连接尚未开始。checking
: 正在检查 ICE 候选者。connected
: 已建立 ICE 连接。completed
: 所有候选者已被确认。disconnected
: ICE 连接中断。failed
: ICE 连接失败。closed
: ICE 连接已关闭。
示例:
console.log(peerConnection.iceConnectionState); // "new"
2.3 signalingState
表示信令过程的状态,可能的值包括:
stable
: 无信令交换。have-local-offer
: 本地已经创建并发送 offer。have-remote-offer
: 已收到远端的 offer。have-local-pranswer
: 已发送本地的 provisional answer。have-remote-pranswer
: 已接收到远端的 provisional answer。closed
: 连接已关闭。
示例:
console.log(peerConnection.signalingState); // "stable"
2.4 localDescription
/ remoteDescription
localDescription
: 表示本地设置的 SDP 描述(包括 offer 或 answer)。remoteDescription
: 表示远程设置的 SDP 描述(包括 offer 或 answer)。
示例:
console.log(peerConnection.localDescription);
console.log(peerConnection.remoteDescription);
2.5 pendingLocalDescription
/ pendingRemoteDescription
pendingLocalDescription
: 本地正在进行中的 SDP 描述,尚未完成设置。pendingRemoteDescription
: 远端正在进行中的 SDP 描述,尚未完成设置。
示例:
console.log(peerConnection.pendingLocalDescription);
console.log(peerConnection.pendingRemoteDescription);
3. 方法
3.1 createOffer()
创建一个 SDP offer,用于开始建立连接。
参数:
options
: 一个可选的对象,可以配置 offer 的约束条件。例如,是否只传输视频或音频。
返回值:
返回一个 Promise
,其结果是一个 RTCSessionDescription
对象。
示例:
peerConnection.createOffer().then(offer => {
return peerConnection.setLocalDescription(offer);
});
3.2 createAnswer()
响应远端的 SDP offer,并生成一个 answer。
返回值:
返回一个 Promise
,其结果是一个 RTCSessionDescription
对象。
示例:
peerConnection.createAnswer().then(answer => {
return peerConnection.setLocalDescription(answer);
});
3.3 setLocalDescription()
将本地的 SDP 描述(offer 或 answer)应用于本地。
参数:
RTCSessionDescription
: 描述对象,包含type
(offer
或answer
)和sdp
。
示例:
peerConnection.setLocalDescription(offer);
3.4 setRemoteDescription()
将远程 SDP 描述应用于连接。
参数:
RTCSessionDescription
: 远程描述对象。
示例:
peerConnection.setRemoteDescription(remoteOffer);
3.5 addIceCandidate()
向 RTCPeerConnection
添加一个新的 ICE 候选者,用于更新连接状态。
参数:
RTCIceCandidate
: ICE 候选对象,包含候选者的地址和相关信息。
示例:
peerConnection.addIceCandidate(new RTCIceCandidate(candidate));
3.6 createDataChannel()
创建一个 RTCDataChannel
,用于在对等连接中传输任意数据。RTCDataChannel
可以在两个客户端之间实现低延迟的数据传输。
参数:
label
: 数据通道的标签。options
: 一个可选对象,用于配置数据通道的属性,如ordered
、maxRetransmits
等。
示例:
const dataChannel = peerConnection.createDataChannel("chat", { ordered: true });
dataChannel.onopen = () => {
console.log("Data channel is open");
};
dataChannel.onmessage = (event) => {
console.log("Message from data channel:", event.data);
};
3.7 addTrack()
将媒体轨道添加到连接中。通常用于添加音频或视频轨道。
参数:
MediaStreamTrack
: 要添加的媒体轨道。MediaStream
: 包含轨道的媒体流。
示例:
navigator.mediaDevices.getUserMedia({ video: true, audio: true })
.then(stream => {
stream.getTracks().forEach(track => peerConnection.addTrack(track, stream));
});
3.8 getStats()
返回当前连接的统计数据,数据包括带宽使用情况、丢包率等信息。
示例:
peerConnection.getStats().then(stats => {
stats.forEach(report => {
console.log(report.type, report);
});
});
3.9 close()
关闭连接并释放资源。关闭后无法再使用此连接。
示例:
peerConnection.close();
4. 事件
4.1. icecandidate
事件
当新的 ICE 候选(RTCIceCandidate
)可用时,触发此事件。ICE 候选是网络地址信息,用于确定最优的路径来连接两端。
- 事件类型:
RTCPeerConnectionIceEvent
- 常用场景:将 ICE 候选通过信令服务器发送给远端,以帮助建立连接。
- 使用示例:
peerConnection.onicecandidate = (event) => { if (event.candidate) { // 发送 ICE 候选给远端 sendCandidateToRemote(event.candidate); } else { console.log("All ICE candidates have been sent."); } };
4.2. iceconnectionstatechange
事件
当 ICE 连接状态(iceConnectionState
)改变时触发,反映 ICE 的连接状态变化。常见状态包括:
-
new
: 新连接 -
checking
: 正在检查候选路径 -
connected
: 已成功建立连接 -
disconnected
: 连接已断开但可重新连接 -
failed
: 连接建立失败 -
closed
: 连接已关闭 -
事件类型:
Event
-
常用场景:跟踪连接状态,处理连接问题。
-
使用示例:
peerConnection.oniceconnectionstatechange = () => { console.log("ICE Connection State: ", peerConnection.iceConnectionState); };
4.3. signalingstatechange
事件
当信令状态(signalingState
)发生改变时触发,反映 SDP 信令的状态。常见状态包括:
-
stable
: 无 SDP 交换 -
have-local-offer
: 已发送本地 SDP 提议 -
have-remote-offer
: 已接收远端 SDP 提议 -
closed
: 连接已关闭 -
事件类型:
Event
-
常用场景:跟踪信令状态,调试 SDP 交换过程。
-
使用示例:
peerConnection.onsignalingstatechange = () => { console.log("Signaling State: ", peerConnection.signalingState); };
4.4. icegatheringstatechange
事件
当 ICE 收集状态(iceGatheringState
)改变时触发,反映 ICE 候选的收集进程。常见状态包括:
-
new
: 尚未开始收集 -
gathering
: 正在收集候选 -
complete
: 候选收集完成 -
事件类型:
Event
-
常用场景:调试 ICE 候选收集的进度。
-
使用示例:
peerConnection.onicegatheringstatechange = () => { console.log("ICE Gathering State: ", peerConnection.iceGatheringState); };
4.5. connectionstatechange
事件
当整个 RTCPeerConnection
的连接状态(connectionState
)改变时触发,它反映了 WebRTC 连接的整体状态,包括 ICE 和 DTLS 状态。常见状态包括:
-
new
: 新连接 -
connecting
: 正在连接 -
connected
: 连接已建立 -
disconnected
: 连接已断开 -
failed
: 连接失败 -
closed
: 连接已关闭 -
事件类型:
Event
-
常用场景:全面监控连接状态,适时处理断开或失败情况。
-
使用示例:
peerConnection.onconnectionstatechange = () => { console.log("Connection State: ", peerConnection.connectionState); };
4.6. datachannel
事件
当远端创建了数据通道(RTCDataChannel
)时,触发此事件。用于处理数据通道通信。
- 事件类型:
RTCDataChannelEvent
- 常用场景:接收并初始化远端的数据通道,处理双向通信。
- 使用示例:
peerConnection.ondatachannel = (event) => { const receiveChannel = event.channel; receiveChannel.onmessage = (event) => { console.log("Received message:", event.data); }; };
4.7. track
事件
当远端的媒体轨道(音频、视频)被添加到连接中时触发。用于接收音视频流。
- 事件类型:
RTCTrackEvent
- 常用场景:在浏览器中展示远端的音视频流。
- 使用示例:
peerConnection.ontrack = (event) => { const remoteStream = event.streams[0]; // 将远端视频流显示在视频元素中 remoteVideoElement.srcObject = remoteStream; };
4.8. negotiationneeded
事件
当需要重新协商 SDP 时触发,如增加或移除媒体轨道,或创建数据通道时。
- 事件类型:
Event
- 常用场景:主动启动 SDP 协商,确保连接能够传输新的媒体或数据。
- 使用示例:
peerConnection.onnegotiationneeded = async () => { try { const offer = await peerConnection.createOffer(); await peerConnection.setLocalDescription(offer); // 发送 offer 给远端 sendOfferToRemote(offer); } catch (error) { console.error("Error during negotiation:", error); } };
4.9. removetrack
事件
当本地或远端媒体轨道被移除时触发,用于处理轨道的变化。
- 事件类型:
RTCTrackEvent
- 常用场景:处理媒体流中的轨道移除,更新界面或状态。
- 使用示例:
peerConnection.onremovetrack = (event) => { console.log("Track removed:", event.track); };
4.10. statsended
事件(实验性)
当获取到连接的统计信息时触发,可以用于调试和监控 WebRTC 连接的状态。它在 WebRTC 中并不广泛使用。
RTCDataChannel
在 WebRTC 中,RTCPeerConnection
API 允许两个对等端之间进行音频、视频、数据的实时传输。通过 RTCPeerConnection
创建的数据通道(RTCDataChannel
),用户可以发送任意类型的数据,比如文本、文件、二进制数据等。RTCDataChannel
是一个基于双向通信的机制,支持在 WebRTC 连接中实现低延迟、可靠或不可靠的数据传输。
1. 创建 RTCDataChannel
要使用 RTCDataChannel
发送消息,首先需要在 RTCPeerConnection
中创建或接受一个数据通道。
1.1 创建端
创建端是主动建立数据通道的一方,通常通过调用 RTCPeerConnection.createDataChannel()
方法来创建一个数据通道。此方法接受两个参数:
label
:数据通道的标识符,是一个可选的字符串,客户端可以通过此标识符区分多个数据通道。options
:一个可选的配置对象,用于配置通道的行为。
示例代码:
// 创建 RTCPeerConnection 对象
const peerConnection = new RTCPeerConnection();
// 创建数据通道
const dataChannel = peerConnection.createDataChannel("myDataChannel", {
ordered: true, // 确保消息按顺序到达
maxRetransmits: 10 // 最多重传 10 次
});
// 处理数据通道打开事件
dataChannel.onopen = () => {
console.log("Data channel is open");
dataChannel.send("Hello, WebRTC!"); // 发送消息
};
// 处理数据通道关闭事件
dataChannel.onclose = () => {
console.log("Data channel is closed");
};
1.2 接收端
接收端并不会主动创建数据通道,而是监听 datachannel
事件来接收来自创建端的数据通道。
示例代码:
// 处理 datachannel 事件
peerConnection.ondatachannel = (event) => {
const receiveChannel = event.channel;
// 处理接收到的数据
receiveChannel.onmessage = (event) => {
console.log("Received message:", event.data);
};
// 处理数据通道打开事件
receiveChannel.onopen = () => {
console.log("Receive channel is open");
};
// 处理数据通道关闭事件
receiveChannel.onclose = () => {
console.log("Receive channel is closed");
};
};
2. 发送消息
RTCDataChannel.send()
方法用于通过数据通道发送数据。该方法可以发送以下类型的数据:
- 字符串(
string
) Blob
对象ArrayBuffer
ArrayBufferView
(如Uint8Array
)
示例:发送字符串消息
dataChannel.send("This is a text message");
示例:发送二进制数据
const arrayBuffer = new Uint8Array([72, 101, 108, 108, 111]).buffer; // "Hello" in binary
dataChannel.send(arrayBuffer);
3. 关闭数据通道
RTCDataChannel.close()
用于关闭数据通道。一旦关闭,不能再通过此通道发送或接收数据。
示例代码:
dataChannel.close();
4. RTCDataChannel
配置选项
在创建数据通道时,options
参数可用于配置通道的各种属性。常见的属性如下:
ordered
(布尔值):设置消息是否按顺序到达。默认为true
。maxPacketLifeTime
(数字):指定数据报文的最大生命周期(毫秒)。超出生命周期后未送达的消息将被丢弃。maxRetransmits
(数字):指定重传次数的最大值。若达到重传次数仍未送达,消息将被丢弃。protocol
(字符串):设置应用层协议的名称,供双方识别。negotiated
(布尔值):设置是否手动协商数据通道。默认为false
,即自动协商。
5. 错误处理
当数据通道发生错误时,RTCDataChannel.onerror
事件会被触发。可以通过此事件处理错误。
示例代码:
dataChannel.onerror = (error) => {
console.error("Data channel error:", error);
};
6. 完整的发送消息示例
// 创建 RTCPeerConnection 对象
const peerConnection = new RTCPeerConnection();
// 创建数据通道
const dataChannel = peerConnection.createDataChannel("chat", {
ordered: true, // 确保按顺序到达
maxRetransmits: 5 // 设置最大重传次数
});
// 处理数据通道事件
dataChannel.onopen = () => {
console.log("Data channel is open");
// 发送消息
dataChannel.send("Hello, this is WebRTC dataChannel");
};
dataChannel.onmessage = (event) => {
console.log("Received:", event.data);
};
dataChannel.onclose = () => {
console.log("Data channel is closed");
};
// 处理错误事件
dataChannel.onerror = (error) => {
console.error("Data channel error:", error);
};
7. 总结
- 数据通道创建:通过
RTCPeerConnection.createDataChannel()
方法在主动端创建数据通道,接收端通过datachannel
事件监听数据通道。 - 消息发送:通过
RTCDataChannel.send()
方法发送数据,支持多种数据类型,包括字符串、二进制数据等。 - 事件处理:数据通道有多个事件可以处理,包括
onopen
、onmessage
、onclose
和onerror
,用于跟踪数据通道状态及错误。 - 关闭数据通道:使用
RTCDataChannel.close()
方法关闭数据通道,释放资源。