Google 致力于为黑人社区推动种族平等。查看具体行动
此页面由 Cloud Translation API 翻译。
Switch to English

对等连接入门

对等连接是WebRTC规范的一部分,它涉及连接不同计算机上的两个应用程序以使用对等协议进行通信。对等方之间的通信可以是视频,音频或任意二进制数据(对于支持RTCDataChannel API的客户端)。为了发现两个对等方如何连接,两个客户端都需要提供ICE服务器配置。它可以是STUN服务器,也可以是TURN服务器,它们的作用是为每个客户端提供ICE候选对象,然后将其转移到远程对等方。 ICE候选者的这种转移通常称为信令。

发信号

WebRTC规范包括用于与ICE(Internet连接建立)服务器进行通信的API,但是信令组件不是其中的一部分。为了使两个对等方共享它们应如何连接,需要发出信号。通常,这可以通过基于常规HTTP的Web API(即REST服务或其他RPC机制)解决,其中Web应用程序可以在启动对等连接之前中继必要的信息。

以下代码段显示了如何将此虚拟信令服务用于异步发送和接收消息。如有必要,将在本指南的其余示例中使用它。

 // Set up an asynchronous communication channel that will be
// used during the peer connection setup
const signalingChannel = new SignalingChannel(remoteClientId);
signalingChannel.addEventListener('message', message => {
    // New message from remote client received
});

// Send an asynchronous message to the remote client
signalingChannel.send('Hello!');
 

信令可以通过许多不同的方式来实现,并且WebRTC规范不喜欢任何特定的解决方案。

启动对等连接

每个对等连接均由RTCPeerConnection对象处理。此类的构造函数将单个RTCConfiguration对象作为其参数。该对象定义了对等连接的建立方式,并应包含有关要使用的ICE服务器的信息。

创建RTCPeerConnection ,我们需要创建SDP服务或应答,具体取决于我们是呼叫对等方还是接收对等方。创建SDP报价或答案后,必须通过其他渠道将其发送到远程对等方。将SDP对象传递给远程对等点称为信令,并且不属于WebRTC规范。

要从调用方启动对等连接设置,我们创建一个RTCPeerConnection对象,然后调用createOffer()创建一个RTCSessionDescription对象。使用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});
}
 

在接收方,我们在创建RTCPeerConnection实例之前等待收到的报价。完成后,我们使用setRemoteDescription()设置收到的报价。接下来,我们调用createAnswer()为收到的报价创建答案。使用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,并且正在使用STUN或TURN服务器。 STUN代表NAT的会话遍历实用程序,通常在大多数WebRTC应用程序中间接使用。

TURN(使用中继NAT进行遍历)是更高级的解决方案,它结合了STUN协议,大多数基于WebRTC的商业服务都使用TURN服务器在对等体之间建立连接。 WebRTC API直接支持STUN和TURN,并且收集在更完整的术语Internet连接建立中。创建WebRTC连接时,我们通常在RTCPeerConnection对象的配置中提供一台或几台ICE服务器。

ckle流冰

创建RTCPeerConnection对象后,基础框架将使用提供的ICE服务器收集用于建立连接的候选对象(ICE候选对象)。事件icegatheringstatechangeRTCPeerConnection信号处于什么状态ICE聚会是( newgatheringcomplete )。

尽管对等方可以等到ICE收集完成后,使用“细流冰”技术并在发现每个ICE候选方时将其发送给远程对等方通常效率更高。这将显着减少对等连接的建立时间,并允许视频通话以更少的延迟开始。

要收集ICE候选者,只需为icecandidate事件添加一个侦听器。在该侦听器上发出的RTCPeerConnectionIceEvent将包含candidate属性,该属性表示应发送给远程对等方的新候选(请参阅信令)。

 // 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);
        }
    }
});
 

连接已建立

收到ICE候选者后,我们应该期望对等连接的状态最终将变为连接状态。为了检测到这一点,我们在RTCPeerConnection中添加了一个侦听器,在其中侦听connectionstatechange事件。

 // Listen for connectionstatechange on the local RTCPeerConnection
peerConnection.addEventListener('connectionstatechange', event => {
    if (peerConnection.connectionState === 'connected') {
        // Peers connected!
    }
});
 

RTCPeerConnection API文档