为什么webbrtc只在第二次报价后才建立连接?



我想建立一个WebRTC数据通道并发送一些文本。因此,我创建了一个RTCPeerConnection对象和一个"oniccandidate"。和";ondatachannel"处理程序。(我保持"配置";for 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后,它接收到一个答案,但是"iceGatheringState"one_answers";iceConnectionState"RTCPeerConnection保持"新"状态。没有"onicecandidate"触发事件。在A再次调用createOffer()之后,报价看起来"更大了"。(包含更多值)。在将第二次报价设置为本地描述"一个候选人"后;事件发生在双方。但数据通道只有在A向b发送第二个报价后才建立。

我知道这是同样的问题,但答案似乎不合适,因为我有一个"优秀的候选人"。处理程序。我也读了关于涓流冰的文章,但仍然不知道问题是什么。

必须在协商之前至少调用一次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时自动触发协商,后续不触发协商。

但如果你在两端都这样做,要小心眩光,或者使用完美的谈判模式。

相关内容

最新更新