Javascript 为什么WebRTC仅在第二次提供后才建立连接?

Javascript 为什么WebRTC仅在第二次提供后才建立连接?,javascript,webrtc,Javascript,Webrtc,我想设置一个WebRTC数据通道并发送一些文本。因此,我创建了一个带有“onicecandidate”和“ondatachannel”处理程序的RTPeerConnection对象。(我将RTPeerConnection的“配置”保留为空,因为连接仅在本地主机之间。) 那我就把报价从A寄到B offer = await myConnection.createOffer(); await myConnection.setLocalDescription(offer); send({type: &q

我想设置一个WebRTC数据通道并发送一些文本。因此,我创建了一个带有“onicecandidate”和“ondatachannel”处理程序的RTPeerConnection对象。(我将RTPeerConnection的“配置”保留为空,因为连接仅在本地主机之间。)

那我就把报价从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});
}
将其设置为远程描述并打开数据通道

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发送第一个要约后,会收到一个答复,但RTPeerConnection的“ICeColgatingState”和“iceConnectionState”保持为“新”。未触发任何“onicecandidate”事件。再次调用createOffer()后,该提供看起来“更大”(包含更多值)。将第二个要约设置为本地描述后,双方都会触发“onicecandicate”事件。但数据通道只有在A向B发送第二个报价后才建立


我知道是同一个问题,但答案似乎不合适,因为我有一个“onicecandidate”处理程序。我也读过关于涓流冰的文章,但仍然不知道问题出在哪里。

您必须在协商之前至少调用一次myConnection.createDataChannel,让连接协商数据通道的使用。默认情况下不包括它们

在那之前没有媒体和数据通道,没有什么可以协商的。这使得您的第一次协商变得多余,没有操作,这就是为什么州政府从不离开“新”

完成此操作后,无需再次执行,因为所有后续数据通道都通过相同的sctp传输进行多路复用

仅在需要时进行协商,考虑设置:

pc.onnegotiationneeded = async () => {
  try {
    await pc.setLocalDescription(await pc.createOffer());
    send({type: "offer", offer: pc.localDescription});
  } catch (e) {
    console.error(e);
  }
};
然后,当您第一次调用
pc.createDataChannel
时(但不是后续时间),协商将自动触发

但是如果你在两端都这样做,或者使用这种模式,要小心眩光

pc.onnegotiationneeded = async () => {
  try {
    await pc.setLocalDescription(await pc.createOffer());
    send({type: "offer", offer: pc.localDescription});
  } catch (e) {
    console.error(e);
  }
};