RTCDataChannel发送方法不发送数据

时间:2016-05-04 11:44:47

标签: javascript html5 webrtc rtcdatachannel

我对RTCDataChannel有一个奇怪的问题。

我正在研究WebRTC,我已经开始进行WebRTC音频/视频聊天了。现在我想使用RTCDataChannel为它添加文本聊天和文件共享。

我已经像这样创建了RTCDataChannel:

var dataChannelOptions = {
    reliable: true,
    maxRetransmitTime: "2000"
};

dataChannel = yourConnection.createDataChannel("testDataChannel", dataChannelOptions);

dataChannel.onerror = function (error) {
    console.log("dataChannel.OnError:", error);
};

dataChannel.onmessage = function (event) {
    console.log("dataChannel.OnMessage:", event);
};

dataChannel.onopen = function (event) {
    console.log("dataChannel.OnOpen", event);
    dataChannel.send("Hello World!");
};

dataChannel.onclose = function (event) {
    console.log("dataChannel.OnClose", event);
};

我唯一接受的是从 dataChannel.onopen 的第一行登录。我没有从 dataChannel.onmessage 收到日志。

没有错误..

当我手动调用 dataChannel.send 时,结果是一样的。

测试:
谷歌浏览器(50.0.2661.94)
Firefox(45.0.2)

任何人都可以提供帮助吗?

4 个答案:

答案 0 :(得分:12)

这是人们常犯的错误,你在两个浏览器上创建数据通道,但不接受任何一个,你需要使用RTCPeerConnection的ondatachannel事件并设置监听器

答案 1 :(得分:4)

我遇到了同样的问题。根据RTCDataChannel文档,您应该处理Peer Connection对象上的回调以接收数据通道上的数据。下面的代码可能会有所帮助:

第1步:定义回调处理程序:

  var handleDataChannelOpen = function (event) {
    console.log("dataChannel.OnOpen", event);
    dataChannel.send("Hello World!");
  };

  var handleDataChannelMessageReceived = function (event) {
    console.log("dataChannel.OnMessage:", event);
  };

  var handleDataChannelError = function (error) {
    console.log("dataChannel.OnError:", error);
  };

  var handleDataChannelClose = function (event) {
    console.log("dataChannel.OnClose", event);
  };

  var handleChannelCallback = function (event) {
     dataChannel = event.channel;
     dataChannel.onopen = handleDataChannelOpen;
     dataChannel.onmessage = handleDataChannelMessageReceived;
     dataChannel.onerror = handleDataChannelError;
     dataChannel.onclose = handleDataChannelClose;
  };

步骤2:创建RTC对等连接:

  var pc = new RTCPeerConnection();
  pc.ondatachannel = handleChannelCallback;

第3步:创建数据通道:

  var dataChannel = pc.createDataChannel('dataChannelName', {});

  dataChannel.onopen = handleDataChannelOpen;
  dataChannel.onmessage = handleDataChannelMessageReceived;
  dataChannel.onerror = handleDataChannelError;
  dataChannel.onclose = handleDataChannelClose;

在您的代码中,您只需添加ondatachannel回调处理程序即可接收数据。

答案 2 :(得分:0)

我认为最大的错误观念,至少对我来说,每个客户都需要保留对两个频道的引用(如果错误,请纠正我,因为它根本感觉不对) 。一个用于发送,一个用于接收。这基本上是@Nikhil的回答。他为处理程序创建了命名函数,以便使用它们两次。

另请注意,您可以在peerConnection实例化后立即定义数据连接。我已经阅读了相互矛盾的事情,说你必须只从调用者那里做,或者只有在连接准备好之后才能这样做。也许对于旧版本的WebRTC来说也是如此,但这适用于当前的chrome(从2017年10月开始)。

let pc = new RTCPeerConnection({"iceServers": [{"url": "stun:stun.l.google.com:19302"}]});

const handleDataChannelOpen = (event) =>{
    console.log("dataChannel.OnOpen", event);
    sendChannel.send("Hello World!");
};

const handleDataChannelMessageReceived = (event) =>{
    console.log("dataChannel.OnMessage:", event);
};

const handleDataChannelError = (error) =>{
    console.log("dataChannel.OnError:", error);
};

const handleDataChannelClose = (event) =>{
    console.log("dataChannel.OnClose", event);
};


let sendChannel = pc.createDataChannel('text', {});
sendChannel.onopen = handleDataChannelOpen;
sendChannel.onmessage = handleDataChannelMessageReceived;
sendChannel.onerror = handleDataChannelError;
sendChannel.onclose = handleDataChannelClose;


pc.ondatachannel = (event) =>{
    console.log("on data channel")
    let receiveChannel = event.channel;
    receiveChannel.onopen = handleDataChannelOpen;
    receiveChannel.onmessage = handleDataChannelMessageReceived;
    receiveChannel.onerror = handleDataChannelError;
    receiveChannel.onclose = handleDataChannelClose;

    let button = document.getElementById(this.id + "-submit");
    button.onclick = () =>{
        receiveChannel.send("hello from " + this.id)
    };
};

//... do your connection with servers

答案 3 :(得分:0)

这是有效的客户端代码,我在这里分享,也许可以帮助到别人。请感谢它是否对您有帮助:

            var connection = new WebSocket('wss://127.0.0.1:3000'); 
            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) {
            //    if(message)
                var data = JSON.parse(message.data);
                console.log("Got message", data.type);
               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 RTCPeerConnection(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 
                        });
                     } 
                  }; 
                  myConnection.ondatachannel = function (event) {
                      var receiveChannel = event.channel;
                      receiveChannel.onmessage = function (event) {
                          console.log("ondatachannel message:", event.data);
                      };
                  }; 

                  openDataChannel();
                  console.log("DataChannel Opened..");

               } 
            };

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

            //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(offer); 

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


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