WebRTC技术问题:SDP应答中未添加DataChannel的原因咨询
WebRTC:无法在SDP Answer中添加DataChannel的原因与解决办法
为什么你的代码不生效?
WebRTC的Offer-Answer模型有个硬规矩:Answer只能对Offer里已经存在的媒体类型做回应(同意、拒绝或修改参数),不能凭空新增Offer里没有的媒体流/通道。
你现在的情况是:收到的Offer里没有m=application字段(因为发起方没创建DataChannel),这时候你在调用createAnswer()前调用createDataChannel(),浏览器根本不会把这个通道的信息塞进Answer里——因为这超出了本次协商的范围,浏览器不会允许你这么做。
怎么让应答方创建DataChannel?
有两种靠谱的方案,看你需求选择:
方案1:连接建立后再创建(推荐)
WebRTC允许在PeerConnection的connectionState变成connected(也就是ICE连通、P2P链路建好)之后,任何一方直接调用createDataChannel(),完全不用修改SDP。这时候DataChannel会走已经建好的P2P链路,发起方会通过datachannel事件收到这个通道。
示例代码:
// 应答方处理Offer的逻辑 if (type === 'offer') { peerConnection.setRemoteDescription(new RTCSessionDescription(offer)) .then(() => peerConnection.createAnswer()) .then(answer => peerConnection.setLocalDescription(answer)) .then(() => { // 把Answer发给发起方 sendToPeer(peerConnection.localDescription); }) .catch(err => console.error(err)); } // 等连接建好后创建DataChannel peerConnection.addEventListener('connectionstatechange', () => { if (peerConnection.connectionState === 'connected') { const dc = peerConnection.createDataChannel('some/channel'); dc.addEventListener('open', () => { dc.send('Hey, 我是应答方创建的通道!'); }); dc.addEventListener('message', e => console.log('收到消息:', e.data)); } }); // 发起方接收通道的逻辑 peerConnection.addEventListener('datachannel', e => { const receiveDc = e.channel; receiveDc.addEventListener('message', e => console.log('应答方发消息了:', e.data)); });
方案2:让应答方发起新的Offer
如果硬要在SDP里带上DataChannel的信息,那得让原本的应答方当一次Offer发起方:
- 先完成基础的Offer-Answer协商(不带DataChannel),建好P2P连接。
- 原本的应答方调用
createDataChannel(),然后生成新的Offer,这个Offer里就会有m=application字段。 - 原本的发起方应答这个新的Offer,完成DataChannel的协商。
这种方式需要两次协商,适合必须在SDP里明确DataChannel信息的场景。
总结
- 你之前的代码不行,是因为违反了Offer-Answer模型的规则,Answer不能新增Offer没有的媒体类型。
- 绝大多数场景用方案1就够了,流程简单,不需要折腾SDP。
- 非要在SDP里带DataChannel信息,就用方案2,让需要创建通道的一方发起Offer。
内容的提问来源于stack exchange,提问作者JonasVautherin
相关产品推荐
相关产品推荐

