WebRTC-RTCPeerConnection API

RTCPeerConnection API是每个浏览器之间对等连接的核心。要创建RTCPeerConnection对象,只需编写:

var pc = RTCPeerConnection(config);

其中config参数至少包含密钥iceServers。它是一个URL对象数组,包含有关STUN和TURN服务器的信息,用于查找ICE候选对象。您可以在code.google.com上找到可用的公共STUN服务器列表。

根据您是调用方还是被调用方,RTCPeerConnection对象在连接的两边使用的方式略有不同。

这是用户流程的示例:

  • 注册onicecandidate处理程序。接收到任何ICE候选者后,它将ICE候选者发送给其他对等体。
  • 注册onaddstream处理程序。一旦从远程对等方接收到视频流,它将处理视频流的显示。
  • 注册消息处理程序。您的信令服务器还应该具有一个处理程序,用于处理从其他对等方接收到的消息。如果消息包含RTCSessionDescription对象,则应使用setRemoteDescription()方法将其添加到RTCPeerConnection对象。如果消息包含RTCIceCandidate对象,则应使用addIceCandidate()方法将其添加到RTCPeerConnection对象。
  • 利用getUserMedia()设置本地媒体流,并使用addStream()方法将其添加到RTCPeerConnection对象。
  • 开始报价/答案协商过程。这是呼叫者的流程与被呼叫者的流程不同的唯一步骤。调用方使用createOffer()方法开始协商,并注册一个接收RTCSessionDescription对象的回调。然后,此回调应使用setLocalDescription()将此RTCSessionDescription对象添加到您的RTCPeerConnection对象。最后,调用者应使用信令服务器将此RTCSessionDescription发送到远程对等方。另一方面,被调用方注册了相同的回调,但是在createAnswer()中方法。请注意,仅在收到来自主叫方的报价后,才启动被叫方流程。

RTCPeerConnection API

属性:

  • RTCPeerConnection.iceConnectionState(只读) -返回描述连接状态的RTCIceConnectionState枚举。当该值更改时,将触发iceconnectionstatechange事件。可能的值-
    • -ICE代理正在等待远程候选者或收集地址
    • 检查-ICE代理具有远程候选者,但尚未找到连接
    • 已连接-ICE代理已找到可用的连接,但仍在检查更多的远程候选者以获得更好的连接。
    • 已完成-ICE代理已找到可用的连接,并停止测试远程候选对象。
    • 失败-ICE代理检查了所有远程候选者,但没有找到至少一个组件的匹配项。
    • 断开连接-至少一个组件不再活动。
    • 已关闭-ICE代理已关闭。
  • RTCPeerConnection.iceGatheringState(只读) -返回描述连接的ICE收集状态的RTCIceGatheringState枚举-
    • new-该对象刚刚创建。
    • 收集-ICE代理正在收集候选人
    • 完成ICE代理已完成收集。
  • RTCPeerConnection.localDescription(只读) -返回描述本地会话的RTCSessionDescription。如果尚未设置,则可以为null。
  • RTCPeerConnection.peerIdentity(只读) -返回RTCIdentityAssertion。它由一个idp(域名)和一个代表远程对等方身份的名称组成。
  • RTCPeerConnection.remoteDescription(只读) -返回描述远程会话的RTCSessionDescription。如果尚未设置,则可以为null。
  • RTCPeerConnection.signalingState(只读) -返回描述本地连接的信令状态的RTCSignalingState枚举。此状态描述了SDP报价。当此值更改时,将触发signalingstatechange事件。可能的值-
    • 稳定-初始状态。没有正在进行的SDP报价/答案交换。
    • have-local-offer-连接的本地已在本地应用了SDP报价。
    • 有远程报价-连接的远程端已在本地应用了SDP报价。
    • have-local-pranswer-已应用远程SDP报价,并在本地应用SDP pranswer。
    • have-remote-pranswer-已应用本地SDP,并且已远程应用SDP pranswer。
    • 已关闭-连接已关闭。

事件处理程序

下面给出的是RTCPeerConnection的常用事件处理程序。

序号事件处理程序和描述
1个RTCPeerConnection.onaddstream触发addstream事件时,将调用此处理程序。远程对等方将MediaStream添加到此连接时,将发送此事件。
2RTCPeerConnection.ondatachannel触发datachannel事件时,将调用此处理程序。将RTCDataChannel添加到此连接时,将发送此事件。
3RTCPeerConnection.onicecandidate触发icecandidate事件时,将调用此处理程序。将RTCIceCandidate对象添加到脚本时发送此事件。
4RTCPeerConnection.oniceconnectionstatechange触发iceconnectionstatechange事件时,将调用此处理程序。iceConnectionState的值更改时,将发送此事件。
5RTCPeerConnection.onidentityresult触发identityresult事件时,将调用此处理程序。在创建要约或通过getIdentityAssertion()进行答复的过程中生成身份声明时,发送此事件。
6RTCPeerConnection.onidpassertion错误触发idpassertionerror事件时,将调用此处理程序。当IdP(身份提供程序)在生成身份声明时发现错误时,将发送此事件。
7RTCPeerConnection.onidpvalidation触发idpvalidationerror事件时,将调用此处理程序。当IdP(身份提供程序)在验证身份声明时发现错误时,将发送此事件。
8需要RTCPeerConnection.onnegotiation触发needingneeded事件时,将调用此处理程序。此事件由浏览器发送,以通知将来需要进行协商。
9RTCPeerConnection.onpeeridentity触发peeridentity事件时,将调用此处理程序。在此连接上设置并验证对等身份后,将发送此事件。
10RTCPeerConnection.onremovestream触发signalingstatechange事件时,将调用此处理程序。当signalingState的值更改时,将发送此事件。
11RTCPeerConnection.onsignalingstatechange触发removestream事件时,将调用此处理程序。从此连接中删除MediaStream时,将发送此事件。

方法

下面给出的是RTCPeerConnection的常用方法。

序号方法与说明
1个RTCPeerConnection()返回一个新的RTCPeerConnection对象。
2RTCPeerConnection.createOffer()创建要约(请求)以查找远程对等方。此方法的前两个参数是成功和错误回调。可选的第三个参数是选项,例如启用音频或视频流。
3RTCPeerConnection.createAnswer()在报价/答案协商过程中为远程对等方收到的报价创建答案。此方法的前两个参数是成功和错误回调。可选的第三个参数是要创建的答案的选项。
4RTCPeerConnection.setLocalDescription()更改本地连接描述。该描述定义了连接的属性。该连接必须能够支持新旧描述。该方法具有三个参数:RTCSessionDescription对象,描述更改成功的回调,描述更改失败的回调。
5RTCPeerConnection.setRemoteDescription()更改远程连接描述。该描述定义了连接的属性。该连接必须能够支持新旧描述。该方法采用三个参数:RTCSessionDescription对象,描述更改成功的回调,描述更改失败的回调。
6RTCPeerConnection.updateIce()更新ping远程候选者并收集本地候选者的ICE代理程序。
7RTCPeerConnection.addIceCandidate()向ICE代理提供远程候选者。
8RTCPeerConnection.getConfiguration()返回RTCConfiguration对象。它表示RTCPeerConnection对象的配置。
9RTCPeerConnection.getLocalStreams()返回本地MediaStream连接的数组。
10RTCPeerConnection.getRemoteStreams()返回远程MediaStream连接的数组。
11RTCPeerConnection.getStreamById()通过给定的ID返回本地或远程MediaStream。
12RTCPeerConnection.addStream()将MediaStream添加为本地视频或音频源。
13RTCPeerConnection.removeStream()删除MediaStream作为本地视频或音频源。
14RTCPeerConnection.close()关闭连接。
15RTCPeerConnection.createDataChannel()创建一个新的RTCDataChannel。
16RTCPeerConnection.createDTMFSender()创建一个与特定MediaStreamTrack关联的新RTCDTMFSender。允许通过连接发送DTMF(双音多频)电话信令。
17RTCPeerConnection.getStats()创建一个新的RTCStatsReport,其中包含有关连接的统计信息。
18岁RTCPeerConnection.setIdentityProvider()设置IdP。具有三个参数-名称,用于通信的协议和可选的用户名。
19RTCPeerConnection.getIdentityAssertion()收集身份声明。不应在应用程序中处理此方法。因此,您可以明确地将其称为仅预期需求。

建立连接

现在让我们创建一个示例应用程序。首先,通过“节点服务器”运行我们在“信令服务器”教程中创建的信令服务器。

页面上将有两个文本输入,一个用于登录,另一个用于我们要连接的用户名。创建一个index.html文件并添加以下代码:

<html lang = "en"> 
   <head> 
      <meta charset = "utf-8" /> 
   </head>
	
   <body> 
	
      <div> 
         <input type = "text" id = "loginInput" /> 
         <button id = "loginBtn">Login</button> 
      </div> 
	
      <div> 
         <input type = "text" id = "otherUsernameInput" />
         <button id = "connectToOtherUsernameBtn">Establish connection</button> 
      </div> 
		
      <script src = "client2.js"></script>
		
   </body>
	
</html>

可以看到,我们已经添加了用于登录的文本输入,登录按钮,用于其他对等用户名的文本输入以及“连接至他”按钮。现在创建一个client.js文件并添加以下代码:

var connection = new WebSocket('ws://localhost:9090'); 
var name = ""; 
 
var loginInput = document.querySelector('#loginInput'); 
var loginBtn = document.querySelector('#loginBtn'); 
var otherUsernameInput = document.querySelector('#otherUsernameInput'); 
var connectToOtherUsernameBtn = document.querySelector('#connectToOtherUsernameBtn'); 
var connectedUser, myConnection;
  
//when a user clicks the login button 
loginBtn.addEventListener("click", function(event){ 
   name = loginInput.value; 
	
   if(name.length > 0){ 
      send({ 
         type: "login", 
         name: name 
      }); 
   } 
	
});
  
//handle messages from the server 
connection.onmessage = function (message) { 
   console.log("Got message", message.data);
   var data = JSON.parse(message.data); 
	
   switch(data.type) { 
      case "login": 
         onLogin(data.success); 
         break; 
      case "offer": 
         onOffer(data.offer, data.name); 
         break; 
      case "answer": 
         onAnswer(data.answer); 
         break; 
      case "candidate": 
         onCandidate(data.candidate); 
         break; 
      default: 
         break; 
   } 
};
  
//when a user logs in 
function onLogin(success) { 

   if (success === false) { 
      alert("oops...try a different username"); 
   } else { 
      //creating our RTCPeerConnection object 
		
      var configuration = { 
         "iceServers": [{ "url": "stun:stun.1.google.com:19302" }] 
      }; 
		
      myConnection = new webkitRTCPeerConnection(configuration); 
      console.log("RTCPeerConnection object was created"); 
      console.log(myConnection); 
  
      //setup ice handling
      //when the browser finds an ice candidate we send it to another peer 
      myConnection.onicecandidate = function (event) { 
		
         if (event.candidate) { 
            send({ 
               type: "candidate", 
               candidate: event.candidate 
            }); 
         } 
      }; 
   } 
};
  
connection.onopen = function () { 
   console.log("Connected"); 
};
  
connection.onerror = function (err) { 
   console.log("Got error", err); 
};
  
// Alias for sending messages in JSON format 
function send(message) { 

   if (connectedUser) { 
      message.name = connectedUser; 
   } 
	
   connection.send(JSON.stringify(message)); 
};

您可以看到我们建立了到信令服务器的套接字连接。当用户单击登录按钮时,应用程序会将其用户名发送到服务器。如果登录成功,则应用程序将创建RTCPeerConnection对象并设置onicecandidate处理程序,该处理程序将所有找到的icecandidates发送到另一个对等方。现在打开页面并尝试登录。您应该看到以下控制台输出:

WebRTC-RTCPeerConnection API

下一步是向其他同伴创建要约。将以下代码添加到client.js文件中:

//setup a peer connection with another user 
connectToOtherUsernameBtn.addEventListener("click", function () { 
 
   var otherUsername = otherUsernameInput.value; 
   connectedUser = otherUsername;
	
   if (otherUsername.length > 0) { 
      //make an offer 
      myConnection.createOffer(function (offer) { 
         console.log(); 
         send({ 
            type: "offer", 
            offer: offer 
         });
			
         myConnection.setLocalDescription(offer); 
      }, function (error) { 
         alert("An error has occurred."); 
      }); 
   } 
}); 
 
//when somebody wants to call us 
function onOffer(offer, name) { 
   connectedUser = name; 
   myConnection.setRemoteDescription(new RTCSessionDescription(offer)); 
	
   myConnection.createAnswer(function (answer) { 
      myConnection.setLocalDescription(answer); 
		
      send({ 
         type: "answer", 
         answer: answer 
      }); 
		
   }, function (error) { 
      alert("oops...error"); 
   }); 
}
  
//when another user answers to our offer 
function onAnswer(answer) { 
   myConnection.setRemoteDescription(new RTCSessionDescription(answer)); 
} 
 
//when we got ice candidate from another user 
function onCandidate(candidate) { 
   myConnection.addIceCandidate(new RTCIceCandidate(candidate)); 
}	

您可以看到,当用户单击“建立连接”按钮时,应用程序向另一对等方发出SDP报价。我们还设置了onAnsweronCandidate处理程序。重新加载页面,在两个选项卡中打开它,使用两个用户登录并尝试在他们之间建立连接。您应该看到以下控制台输出:

WebRTC-RTCPeerConnection API

现在,对等连接已建立。在接下来的教程中,我们将添加视频和音频流以及文本聊天支持。

作者:terry,如若转载,请注明出处:https://www.web176.com/webrtc/749.html

(0)
打赏 支付宝 支付宝 微信 微信
terryterry
上一篇 2020年10月29日 下午5:43
下一篇 2020年10月29日 下午5:55

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注