🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] ## 概述 - 对等连接是WebRTC规范的一部分,它涉及连接不同计算机上的两个应用程序以使用对等协议进行通信。对等方之间的通信可以是视频,音频或任意二进制数据(对于支持`RTCDataChannel`API的客户端) - 为了发现两个对等方如何连接,两个客户端都需要提供ICE服务器配置。这可以是STUN服务器,也可以是TURN服务器 ## 发信号 ``` const signalingChannel = new SignalingChannel(remoteClientId); signalingChannel.addEventListener('message', message => { // New message from remote client received }); signalingChannel.send('Hello!'); ``` ## 启动对等连接 - 每个对等连接都由`RTCPeerConnection`对象处理 - 创建`RTCPeerConnection`,我们需要创建SDP服务或应答 - 将SDP对象传递到远程对等点称为信令 ### 调用方 1. 我们创建一个`RTCPeerConnection`对象 2. 然后调用`createOffer()`创建一个`RTCSessionDescription`对象。 3. 使用`setLocalDescription()`将该会话描述设置为本地描述,然后通过我们的信令通道发送到接收方 ``` async function makeCall() { const configuration = {'iceServers': [{'urls': 'stun:stun.l.google.com:19302'}]} const peerConnection = new RTCPeerConnection(configuration); signalingChannel.addEventListener('message', async message => { if (message.answer) { const remoteDesc = new RTCSessionDescription(message.answer); await peerConnection.setRemoteDescription(remoteDesc); } }); const offer = await peerConnection.createOffer(); await peerConnection.setLocalDescription(offer); signalingChannel.send({'offer': offer}); } ``` ### 接收方 1. 我们在创建`RTCPeerConnection`实例之前等待收到的报价 2. 我们使用`setRemoteDescription()`设置收到的报价 3. 我们调用`createAnswer()`为收到的报价创建答案 4. 使用`setLocalDescription()`将此答案设置为本地描述,然后通过我们的信令服务器发送到呼叫方 ``` const peerConnection = new RTCPeerConnection(configuration); signalingChannel.addEventListener('message', async message => { if (message.offer) { peerConnection.setRemoteDescription(new RTCSessionDescription(message.offer)); const answer = await peerConnection.createAnswer(); await peerConnection.setLocalDescription(answer); signalingChannel.send({'answer': answer}); } }); ``` 一旦两个对等方都设置了本地和远程会话描述,他们便知道了远程对等方的功能。这并不意味着对等方之间的连接已准备就绪。为此,我们需要在每个对等方收集ICE候选者,并(通过信令信道)转移到另一个对等方 ### ICE候选人 在两个对等方可以使用WebRTC进行通信之前,他们需要交换连接信息。由于网络状况可能取决于许多因素而变化,因此通常使用外部服务来发现可能的候选对象以连接到对等方。这项服务称为ICE #### ckle流冰 创建`RTCPeerConnection`对象后,基础框架将使用提供的ICE服务器收集用于建立连接的候选对象(ICE候选对象)。事件`icegatheringstatechange`上`RTCPeerConnection`信号处于什么状态ICE聚会是(`new`,`gathering`或`complete`) ``` // Listen for local ICE candidates on the local RTCPeerConnection peerConnection.addEventListener('icecandidate', event => { if (event.candidate) { signalingChannel.send({'new-ice-candidate': event.candidate}); } }); // Listen for remote ICE candidates and add them to the local RTCPeerConnection signalingChannel.addEventListener('message', async message => { if (message.iceCandidate) { try { await peerConnection.addIceCandidate(message.iceCandidate); } catch (e) { console.error('Error adding received ice candidate', e); } } }); ``` ### 连接已建立 监听是否连接 ``` // Listen for connectionstatechange on the local RTCPeerConnection peerConnection.addEventListener('connectionstatechange', event => { if (peerConnection.connectionState === 'connected') { // Peers connected! } }); ```