Google is committed to advancing racial equity for Black communities. See how.
本頁面由 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文檔