数据通道
有序/可靠语义、topic 复用、大小限制、消息收发与和 IM 的分工。
数据通道是「RTC 连接上的可靠消息」:适合白板增量、课件指令、光标位置、简单信令;不适合聊天气泡、离线消息、历史记录——那是 IM 的职责(本项目不提供 IM,见 接口定义 的对接边界)。
能力边界(先想清楚再选型)
| 用途 | 数据通道 | IM |
|---|---|---|
| 光标位置 / 白板增量(高频、可丢) | ✅ | ❌ 太慢 |
| 举手、静音指令(低频、要可靠) | ✅ | ✅ |
| 聊天消息 / 离线可达 | ❌ 不保证 | ✅ |
| 大文件传输 | ❌ 不适合 | ✅ 走对象存储 |
数据通道的生命周期绑定在频道连接上:连接断了通道就没了,不会补发。
Web 端用法(签名取自公开接口定义)
import AgoraRTC from '@nimeet/rtc-web';
const client = AgoraRTC.createClient({ mode: 'rtc' });
// 1) 创建并发布一条数据通道:publish 的重载接受 IDataChannelConfig
const dataChannel = await client.publish({ ordered: true }); // ILocalDataChannel
// 2) 发送:二进制载荷(Uint8Array),不是任意 JS 对象
await dataChannel.send(new Uint8Array([1, 2, 3]));
// 3) 接收:远端通道通过 stream-message 投递
client.on('stream-message', (uid, payload) => {
console.log('from', uid, payload.byteLength);
});
// 4) 用完记得取消发布
await client.unpublish(dataChannel);要点:
publish(config)返回ILocalDataChannel,unpublish(dataChannel)收回去;- 载荷是二进制:JSON 要自己
TextEncoder/TextDecoder; - 通道参数(有序、最大重传次数)在
IDataChannelConfig里,发布后可通过dataChannel.getConfig()读回(IDataChannel上有id、maxRetransmits、metadata等只读属性)。
编码约定(团队内统一)
const encoder = new TextEncoder();
const decoder = new TextDecoder();
function sendJson(channel, value) {
return channel.send(encoder.encode(JSON.stringify(value)));
}
client.on('stream-message', (uid, payload) => {
const message = JSON.parse(decoder.decode(payload));
// { t: 'cursor', x, y } / { t: 'whiteboard.op', op }
});加一个 t(type)字段做多路复用,比开多条通道更容易做兼容与埋点。
大小与频率
| 项 | 建议 | 依据 |
|---|---|---|
| 单条载荷 | ≤ 1 KiB 常规,≤ 16 KiB 极限 | 超过 UDP 友好尺寸容易分片重传 |
| 发送频率 | ≤ 30 次/秒 | 更高频事件先在客户端合并 |
| 可靠性 | 指令类用有序可靠;光标类可降级为不可靠 | IDataChannelConfig 的 ordered / maxRetransmits |
原生端
原生端的形状是 sendStreamMessage(streamId, data, length) / createDataStream(config) 这一组(方法是否存在见同端 API 参考), 语义与 Web 一致:先建流、再发消息、收到的回调里按 streamId 分流。
常见问题
| 现象 | 原因 | 处理 |
|---|---|---|
| 收不到消息 | 只 subscribe 了音视频,没处理 stream-message | 确认事件已注册 |
| 发送抛错 | 通道已 unpublish 或连接已断 | 在 connection-state-change 里重建通道 |
| 收到乱码 | 直接把字符串当载荷 | 统一 TextEncoder/TextDecoder |
| 消息重复 | 用了可重传配置 | 业务侧用消息 id 去重 |
| 大消息丢失 | 超过实现上限 | 分片 + 应用层序号 |