You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 19:50:19