RTCDataChannel发送方法未发送数据

RTCDataChannel send method not sending data

本文关键字:数据 方法 RTCDataChannel      更新时间:2023-09-26

我的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.onpen第一行的日志。我没有从dataChannel.onmessage收到日志。

没有错误。。

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

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

有人能帮忙吗?

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

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

步骤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回调处理程序即可接收数据。

我认为最大的误解是,至少对我来说,每个客户都需要保留对两个频道的引用(如果错误,请纠正我,因为感觉根本不对)。一个用于发送,一个用于接收。这基本上就是@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

这是正在工作的客户端代码,我在这里分享,可能对某人有所帮助。如果它对你有帮助,请不胜感激:

            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 "answerswer":
                     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: "answerswer", 
                     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); 
            });