WebRTC - 发送消息

  • 简述

    现在让我们创建一个简单的例子。首先,通过“节点服务器”运行我们在“信令服务器”教程中创建的信令服务器。
    页面上将有三个文本输入,一个用于登录,一个用于用户名,一个用于我们要发送给另一对等点的消息。创建一个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> 
              
          <div> 
             <input type = "text" id = "msgInput" /> 
             <button id = "sendMsgBtn">Send text message</button> 
          </div> 
              
          <script src = "client.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 msgInput = document.querySelector('#msgInput'); 
    var sendMsgBtn = document.querySelector('#sendMsgBtn'); 
    var connectedUser, myConnection, dataChannel;
      
    //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, { 
             optional: [{RtpDataChannels: true}] 
          }); 
              
          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 
                });
             } 
          }; 
              
          openDataChannel();
              
       } 
    };
      
    connection.onopen = function () { 
       console.log("Connected"); 
    }; 
     
    connection.onerror = function (err) { 
       console.log("Got error", err); 
    };
      
    // Mooas for sending messages in JSON format 
    function send(message) { 
       if (connectedUser) { 
          message.name = connectedUser; 
       }
         
       connection.send(JSON.stringify(message)); 
    };
    
    您可以看到我们与信令服务器建立了套接字连接。当用户单击登录按钮时,应用程序将他的用户名发送到服务器。如果登录成功,应用程序将创建RTCPeerConnection对象并设置onicecandidate处理程序,该处理程序将所有找到的 icecandidates 发送给其他对等点。它还运行创建数据通道的 openDataChannel() 函数。请注意,在创建 RTCPeerConnection 对象时,如果您使用的是 Chrome 或 Opera,则构造函数中的第二个参数可选:[{RtpDataChannels: true}] 是必需的。下一步是为其他同行创建报价。将以下代码添加到您的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处理程序。最后,让我们实现创建数据通道的openDataChannel()函数。将以下代码添加到您的client.js文件 -
    
    //creating data channel 
    function openDataChannel() { 
       var dataChannelOptions = { 
          reliable:true 
       }; 
         
       dataChannel = myConnection.createDataChannel("myDataChannel", dataChannelOptions);
         
       dataChannel.onerror = function (error) { 
          console.log("Error:", error); 
       };
         
       dataChannel.onmessage = function (event) { 
          console.log("Got message:", event.data); 
       };  
    }
      
    //when a user clicks the send message button 
    sendMsgBtn.addEventListener("click", function (event) { 
       console.log("send message");
       var val = msgInput.value; 
       dataChannel.send(val); 
    });
    
    在这里,我们为连接创建数据通道,并为“发送消息”按钮添加事件处理程序。现在在两个选项卡中打开此页面,以两个用户登录,建立连接,然后尝试发送消息。您应该在控制台输出中看到它们。请注意,上面的示例是在 Opera 中测试的。
    歌剧中的例子
    现在您可能会看到 RTCDataChannel 是 WebRTC API 中极其强大的部分。这个对象还有很多其他用例,比如点对点游戏或基于 torrent 的文件共享。