我对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) 火狐(45.0.2)
任何人都可以帮忙吗?
这是人们常犯的错误,你在两个浏览器上创建数据通道,但不接受任何一个,你需要使用RTCPeerConnection的ondatachannel
事件并设置监听器
我面临同样的问题。根据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回调处理程序来接收数据。
我认为最大的错误观念,至少对我来说,每个客户都需要保留对两个频道的引用(如果错误,请纠正我,因为它根本感觉不对)。一个用于发送,一个用于接收。这基本上是@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 "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);
});