如何将disconnected状态的RTCPeerConnection重置为初始new状态
RTCPeerConnection 重置状态复用方案
核心结论
RTCPeerConnection 所有连接状态(包括connectionState、iceConnectionState)均为只读属性,无法直接手动修改,状态流转完全由浏览器内核根据协商、网络状态自动控制。你遇到的旧offer协商失败问题是会话上下文失效导致的,和状态没有直接关系:offer中包含了实例生成offer时刻的会话上下文(DTLS指纹、ICE候选、数据/媒体通道配置等),和P2完成协商后这些上下文已经被消费,P2下线后相关会话资源也被标记为失效,旧offer对应的上下文完全不匹配当前实例状态,自然无法用于和第三方协商。
无需新建实例的重置方案
你可以通过以下操作清理现有实例的残留会话资源,将实例重置到可重新协商的初始可用状态:
- 先清理所有残留资源:关闭所有已创建的DataChannel、RTP收发器、已绑定的音视频轨
- 调用
setLocalDescription({type: "rollback"})回滚协商状态到stable - 调用
restartIce()重置ICE连接状态 - 重新生成新的offer与P3完成协商即可,不需要创建新的RTCPeerConnection实例
注意:你之前存储的旧offer已经完全失效,无法再用于和第三方的协商,必须重新生成新的offer。
代码示例
myconnection = new RTCPeerConnection(configuration); dataChannel = myconnection.createDataChannel("channel"); dataChannel.onclose = async ()=>{ console.log("data channel is closed"); console.log(myconnection); //connectionState:disconnected; iceConnectionState: "disconnected" console.log(dataChannel); //readyState: "closed" // 1. 清理所有残留DataChannel myconnection.dataChannels.forEach(channel => channel.close()); // 2. 清理所有RTP收发器 myconnection.getTransceivers().forEach(transceiver => transceiver.stop()); // 3. 回滚协商状态 await myconnection.setLocalDescription({type: "rollback"}); // 4. 重置ICE状态 myconnection.restartIce(); // 现在实例已重置为可用状态,可以重新生成offer和新的端协商 const newOffer = await myconnection.createOffer(); await myconnection.setLocalDescription(newOffer); // 将newOffer发送给P3进行后续协商即可 }
内容的提问来源于stack exchange,提问作者Arijit
相关产品推荐
相关产品推荐

