Ich folgte einem kompletten Tutorial über WebRTC und implementierte einen einfachen P2P-Chat. Mein Signalisierungsserver arbeitet auf localhost: 9090. Wenn ich versuche, eine Nachricht zu senden, erhalte ich:WebRTC: RTCDataChannel ist nicht 'offen'
RTCDataChannel.readyState is not 'open'
Allerdings scheint die Verbindung hergestellt worden ist ordnungsgemäß zu haben:
Connected
Got message {"type":"login","success":true}
RTCPeerConnection object was created
RTCPeerConnection {localDescription: RTCSessionDescription, remoteDescription: RTCSessionDescription, signalingState: "stable", iceGatheringState: "new", iceConnectionState: "new"…}
Channel created
Got message {"type":"answer","answer":{"type":"answer","sdp":"v=0\r\no=- 5123156273253761787 2 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\na=group:BUNDLE data\r\na=msid-semantic: WMS\r\nm=application 9 UDP/TLS/RTP/SAVPF 127\r\nc=IN IP4 0.0.0.0\r\nb=AS:30\r\na=rtcp:9 IN IP4 0.0.0.0\r\na=ice-ufrag:aWnc+x1ot0kpmCj6\r\na=ice-pwd:o8BH8EIsb/FVLBDkUt5Mw6V4\r\na=fingerprint:sha-256 D6:18:83:20:FC:3F:0B:87:8F:FB:D8:5D:D6:33:13:FE:C6:EE:53:3D:18:69:DD:C0:BF:23:35:95:F7:26:4D:F2\r\na=setup:active\r\na=mid:data\r\na=sendrecv\r\na=rtcp-mux\r\na=rtpmap:127 google-data/90000\r\na=ssrc:2024832766 cname:y/zAQto2dzSH04r0\r\na=ssrc:2024832766 msid:myDataChannel myDataChannel\r\na=ssrc:2024832766 mslabel:myDataChannel\r\na=ssrc:2024832766 label:myDataChannel\r\n"}}
Got message {"type":"candidate","candidate":{"candidate":"candidate:2633341356 1 udp 2113937151 172.20.10.6 54721 typ host generation 0 ufrag aWnc+x1ot0kpmCj6","sdpMid":"data","sdpMLineIndex":0}}
candidate added
Hier ist der Code von Client.js ist:
Wie kann ich sicherstellen, dass jeder Client wirklich mit dem anderen verbunden ist und dass die Antwort/SDP korrekt war? Irgendwelche Tipps dazu: Vielleicht ist die Channel-Erstellung zu früh gemacht und sollte erst nach dem ganzen "Handshake" erfolgen? Vielen Dank
__ EDIT Nach Jib der ersten Antwort __
var connectedUser, myConnection, dataChannel;
//when a user clicks the login button
loginBtn.addEventListener("click", function(event) {
name = loginInput.value;
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": [{ "urls": "stun:stun.1.google.com:19302" }]
};
myConnection = new webkitRTCPeerConnection(configuration, {
optional: [{RtpDataChannels: true}]
});
//ondatachannel is defined a bit later, commented out this line.
//myConnection.ondatachannel = event => dataChannel = event.channel;
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.oniceconnectionstatechange = e => console.log(myConnection.iceConnectionState);
myConnection.ondatachannel = function(ev) {
console.log('Data channel is created!');
ev.channel.onopen = function() {
console.log('Data channel is open and ready to be used.');
};
}
}
};
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) {
//Create channel before sending the offer
openDataChannel();
//make an offer
myConnection.createOffer(function (offer) {
send({
type: "offer",
offer: offer
});
myConnection.setLocalDescription(offer);
}, function (error) {
alert("An error has occurred.:", error);
});
}
});
//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: ", 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));
console.log("candidate added");
}
//creating data channel
function openDataChannel() {
var dataChannelOptions = {
reliable:true
};
dataChannel = myConnection.createDataChannel("myDataChannel", dataChannelOptions);
console.log("Channel created");
dataChannel.onerror = function (error) {
console.log("Error:", error);
};
dataChannel.onmessage = function (event) {
console.log("new message received");
console.log("Got message:", event.data);
};
dataChannel.onopen = function() {
console.log("channel opened");
};
}
//when a user clicks the send message button
sendMsgBtn.addEventListener("click", function (event) {
console.log("send message");
var val = msgInput.value;
dataChannel.send(val);
});
Entfernen 'RtpDataChannels' entfernen. Das Zeug ist veraltet, nur für Chrome und funktioniert wahrscheinlich nicht. – jib
Danke Ich kann Daten von dem Benutzer senden, der die Verbindung initiiert (wer einen Datachannel erstellt hat). Wie kann ich Daten mit dem anderen Benutzer zurücksenden, da Sie mir gesagt haben, dass nur 1 einen Datenkanal erstellen muss? – Arkon
Datenkanäle sind bidirektional. Fügen Sie einfach "dataChannel.onmessage" hinzu, um empfangen zu können. – jib