bufferedamount不能只看数值大小,因其反映的是已提交但未确认送达的数据量,滞后于真实网络状态:断连时值可能维持不变,弱网重传堆积时会持续上涨却无错误提示。

bufferedAmount 为什么不能只看数值大小
bufferedAmount 是当前已写入 SCTP 发送缓冲区、但尚未被底层协议确认发出的字节数。它不是“待发送队列长度”,而是“已提交但未确认送达”的数据量。很多开发者误以为只要 bufferedAmount 没到上限(比如 64KB)就安全,其实它滞后于真实网络状态:连接刚断开时,该值可能维持几秒不变;弱网下重传堆积时,它又会持续上涨却无任何错误抛出。
怎么用 bufferedAmount 做有效流量控制
不能等 bufferedAmount 溢出再响应,得主动节流。推荐用轮询 + 阈值回调模式,而非监听事件(WebRTC 没有 onbufferedamountchange):
function waitForBuffer(dataChannel, callback) {
if (dataChannel.bufferedAmount waitForBuffer(dataChannel, callback), 50);
}
}
- 阈值设为
65536(64KB),不是理论最大值,而是实测稳定上限;超过后send()容易静默失败 - 轮询间隔别大于 100ms,太长会导致积压加剧;也别小于 20ms,避免空转耗 CPU
- 务必在
dataChannel.readyState === "open"时才调用,否则bufferedAmount可能为 0 但实际不可发
bufferedAmount 暴涨时真正该做什么
单纯等它降下来没用——它涨说明底层 SCTP 已卡住,可能是对方断连、弱网重传超时或服务端 usrsctp 缓冲区太小(如 ZLMediaKit 默认 256KB,传 H.265 视频时半个 GOP 就溢出)。这时要:
- 立刻停止新消息写入,触发应用层暂停逻辑(比如暂停游戏帧推送、暂停日志批量 flush)
- 检查
peerConnection.connectionState是否为"failed"或"disconnected",而不是只盯dataChannel.readyState - 如果持续 > 2MB 且 5 秒不回落,直接
dataChannel.close()并重建通道——SCTP 缓冲区不会自动清空,卡死状态无法自愈
为什么 onbufferedamountlow 不够用
onbufferedamountlow 是个被动钩子,只在缓冲区从高水位回落时触发一次,且默认阈值不可配。问题在于:
- 它不告诉你“现在是否安全”,只说“刚才降下来了”
- Chrome 和 Firefox 对该事件的触发时机不一致,Firefox 偶尔完全不触发
- 没有配套的
onbufferedamounthigh,无法形成闭环控制
真正可控的方式,是把 bufferedAmount 当作一个需主动 polling 的状态变量,而不是等待事件通知。这点和 WebSocket 的 bufferedAmount 行为完全不同,容易混淆。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











