问题
I'm having a strange problem with RTCDataChannel.
I'm doing some research on WebRTC and I have working WebRTC audio/video chat already. Now I wanted to add text chat and file sharing to it using RTCDataChannel.
I've created RTCDataChannel like this:
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);
};
And only thing that I receieve on both sides is log from first line of dataChannel.onopen. I don't receive log from dataChannel.onmessage.
No errors..
When I manually call dataChannel.send result is the same.
Tested on:
Google Chrome (50.0.2661.94)
Firefox (45.0.2)
Anyone can help with that?
回答1:
this is a common mistake people make, you are creating datachannel on both browsers, but not accepting on either, you need use the RTCPeerConnection's ondatachannel event and set the listeners
回答2:
I was facing the same issue. As per RTCDataChannel documentation, you should handle a callback on Peer Connection object to receive the data on data channel. Below code might be helpful :
Step 1 : Define Callback Handlers :
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;
};
Step 2 : Create RTC Peer Connection :
var pc = new RTCPeerConnection();
pc.ondatachannel = handleChannelCallback;
Step 3 : Create Data Channel :
var dataChannel = pc.createDataChannel('dataChannelName', {});
dataChannel.onopen = handleDataChannelOpen;
dataChannel.onmessage = handleDataChannelMessageReceived;
dataChannel.onerror = handleDataChannelError;
dataChannel.onclose = handleDataChannelClose;
In your code you just need to add ondatachannel callback handler to receive the data.
回答3:
I think the biggest misconception, at least for me, is that each client needs to keep a reference to TWO channels (please correct me if wrong, because it doesn't feel right at all). One for sending, one for receiving. This is basically what @Nikhil's answer is showing. He creates named functions for the handlers, in order to use them twice.
Also note that you can define the data connection right after peerConnection instantiation. I've read conflicting things saying you have to do it from only the caller, or only after the connection is ready. Maybe that was true of older versions of WebRTC but this works in current chrome (whatever is out as of oct 2017).
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
回答4:
This is working Client Side Code, I am sharing here, may be it helped somebody. Please do appreciate if it helped you:
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);
});
来源:https://stackoverflow.com/questions/37026849/rtcdatachannel-send-method-not-sending-data