AWS KVS WebRTC SDK中Master端RTCDataChannel发送消息失败排查
问题描述
我有一个基于Node.js+TypeScript的应用,使用AWS Kinesis Video Streams WebRTC SDK实现了Master与Viewer双端的DataChannel聊天模块。Viewer向Master发送DataChannel消息可正常接收,但Master发送消息时始终抛出错误:
InvalidStateError: Failed to execute 'send' on 'RTCDataChannel': RTCDataChannel.readyState is not 'open'
我已为Master和Viewer监听open、sdpOffer、icecandidate、track事件,请问为何出现该错误?RTCDataChannel的readyState何时会变为'open'?
附master.ts核心代码:
const master: any = { kinesisVideoClient: null, signalingClient: null, channelARN: null, peerConnectionByClientId: {}, dataChannelByClientId: {}, localStream: null, remoteStreams: [], peerConnectionStatsInterval: null }; export const startMaster = async(localView, remoteView, formValues, onStatsReport, onRemoteDataMessage) => { master.localView = localView; master.remoteView = remoteView; // ... 省略KVS客户端创建、信令端点获取等前置代码 ... master.signalingClient.on('sdpOffer', async (offer, remoteClientId) => { printSignalingLog('[MASTER] Received SDP offer from client', remoteClientId); const peerConnection = new RTCPeerConnection(configuration); master.peerConnectionByClientId[remoteClientId] = peerConnection; if (formValues.openDataChannel) { master.dataChannelByClientId[remoteClientId] = peerConnection.createDataChannel('kvsDataChannel'); peerConnection.ondatachannel = event => { event.channel.onmessage = onRemoteDataMessage; }; } // ... 省略ICE候选、Track监听、SDP处理等代码 ... }); // ... 省略其他信令事件监听代码 ... console.log('[MASTER] Starting master connection'); master.signalingClient.open(); }
问题分析与解决方案
1. 错误核心原因
你的Master端代码存在两个关键问题:
- 主动创建DataChannel后未监听其
open状态:Master是主动发起DataChannel的一端,创建后需要等待DataChannel的连接握手完成才能发送消息,你直接尝试发送时,通道可能还处于connecting状态 - 错误使用
peerConnection.ondatachannel:这个事件是给**被动接收DataChannel的一端(Viewer)**用的,Master作为主动创建端,该事件不会触发,导致你既没有正确跟踪Master侧DataChannel的状态,也没有正确绑定消息接收逻辑
2. RTCDataChannel的readyState变化逻辑
RTCDataChannel的状态流转如下:
connecting:创建后的初始状态,此时正在完成ICE连接和通道握手open:当PeerConnection的ICE连接成功建立,且DataChannel的双向握手完成后,状态变为open,此时才能安全调用send()方法closing:通道正在关闭中closed:通道已完全关闭
只有处于open状态时,发送消息才不会抛出状态错误。
3. 代码修复方案
修改Master侧sdpOffer事件中的DataChannel创建逻辑:
if (formValues.openDataChannel) { // 创建DataChannel并保存引用 const dataChannel = peerConnection.createDataChannel('kvsDataChannel'); master.dataChannelByClientId[remoteClientId] = dataChannel; // 监听通道就绪事件,确认可以发送消息 dataChannel.onopen = () => { console.log(`[MASTER] DataChannel with client ${remoteClientId} is ready to send`); // 建议在此回调内触发消息发送,或标记通道就绪状态 }; // 绑定Master侧的消息接收逻辑 dataChannel.onmessage = onRemoteDataMessage; // 监听错误和关闭事件,用于问题排查 dataChannel.onerror = (error) => { console.error(`[MASTER] DataChannel error with client ${remoteClientId}:`, error); }; dataChannel.onclose = () => { console.log(`[MASTER] DataChannel with client ${remoteClientId} closed`); }; // 移除无效的ondatachannel监听(Master是主动创建端,不会触发该事件) // peerConnection.ondatachannel = event => { ... }; }
4. 额外注意事项
- 发送消息前必须检查DataChannel的
readyState,或者在onopen回调中触发发送逻辑 - 确保Viewer侧正确处理Master发起的DataChannel:Viewer需要通过
peerConnection.ondatachannel事件接收通道,并监听其open状态 - 检查PeerConnection的连接状态:通过监听
peerConnection.onconnectionstatechange事件,确认连接状态变为connected,这是DataChannel进入open状态的前提
内容的提问来源于stack exchange,提问作者AMIT SURYA SINGH
相关产品推荐
相关产品推荐

