RTCPeerConnection API 详细介绍(含RTCDataChannel)

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-compatmax-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: 描述对象,包含 typeofferanswer)和 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: 一个可选对象,用于配置数据通道的属性,如 orderedmaxRetransmits 等。
示例:
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() 方法发送数据,支持多种数据类型,包括字符串、二进制数据等。
  • 事件处理:数据通道有多个事件可以处理,包括 onopenonmessageoncloseonerror,用于跟踪数据通道状态及错误。
  • 关闭数据通道:使用 RTCDataChannel.close() 方法关闭数据通道,释放资源。
  • 25
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值