javascript - 为什么 WebRTC 仅在第二次报价后才建立连接?
问题描述
我想建立一个 WebRTC 数据通道并发送一些文本。因此,我创建了一个带有“oniceccandidate”和“ondatachannel”处理程序的 RTCPeerConnection 对象。(我将 RTCPeerConnection 的“配置”保留为空,因为连接仅在本地主机之间。)
var configuration = {};
myConnection = new RTCPeerConnection(configuration);
myConnection.onicecandidate = function (event) {
if (event.candidate) {
send({
type: "candidate",
candidate: event.candidate
});
}
};
myConnection.ondatachannel = function (event) {
dataChannel = event.channel;
dataChannel.onerror = function (error) {
console.log("Error:", error);
};
dataChannel.onmessage = function (event) {
console.log("RTC message:", event.data);
};
};
然后我从 A 向 B 发送报价。
offer = await myConnection.createOffer();
await myConnection.setLocalDescription(offer);
send({type: "offer", offer: offer});
接收器 B 然后发送一个答案。
async function onOffer(offer, name) {
myConnection.setRemoteDescription(new RTCSessionDescription(offer));
answer = await myConnection.createAnswer();
await myConnection.setLocalDescription(answer);
send({type: "answer", answer: answer});
}
其中A设置为远程描述并打开数据通道。
function onAnswer(answer) {
myConnection.setRemoteDescription(new RTCSessionDescription(answer));
openDataChannel();
}
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("RTC message:", event.data);
};
}
还有一个功能可以处理双方收到的候选人。
function onCandidate(candidate) {
myConnection.addIceCandidate(new RTCIceCandidate(candidate));
}
A 发送第一个 offer 后,它收到了一个答复,但 RTCPeerConnection 的“iceGatheringState”和“iceConnectionState”保持“new”。不会触发“onicecandidate”事件。在 A 再次调用 createOffer() 之后,报价看起来“更大”(包含更多值)。将第二个提议设置为本地描述后,双方都会触发“onicecandicate”事件。但数据通道只有在 A 向 B 发送第二个 offer 后才建立。
我知道这是同一个问题,但答案似乎不合适,因为我有一个“oniceccandidate”处理程序。我也读到了涓流冰,但仍然不知道问题是什么。
解决方案
您必须在协商之前myConnection.createDataChannel
至少调用一次,以使连接协商数据通道的使用。默认情况下不包括它们。
在那之前没有媒体,也没有数据通道,没有什么可协商的。这使您的第一次谈判变得多余,成为无操作,这就是国家永远不会离开的原因"new"
。
完成此操作后,无需再次执行此操作,因为所有后续数据通道都通过同一个 sctp 传输多路复用。
要仅在需要时进行协商,请考虑设置:
pc.onnegotiationneeded = async () => {
try {
await pc.setLocalDescription(await pc.createOffer());
send({type: "offer", offer: pc.localDescription});
} catch (e) {
console.error(e);
}
};
pc.createDataChannel
然后,当您第一次调用时(但不是随后的时间),将自动触发协商。
但是,如果您在两端都这样做,或者使用完美的谈判模式,请注意眩光。
推荐阅读
- r - 如何在同一个投影上获得这个栅格和这个 shapefile?
- sql - SQL Select Distinct 查询优化问题
- powershell - 表达几个常用的条件语句
- c - 如何在c中将字符串添加到链表?
- r - (Rcpp, armadillo) 将 arma::vec 转换为 arma::mat
- jquery - SharePoint REST API:复选框组和 GET/POST 的所有值
- php - 从 PHP 7.0 运行 Bash 命令
- swiftui - SwiftUI:在 ScrollView 中居中内容
- c++ - ODBC 中 SQL Server 存储过程的问题绑定输出参数
- git - 将两个 git 存储库合并到一个存储库中,而对原始存储库继续进行更改