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

如何准确统计WebSocket连接的已发送字节数?

WebSocket 发送字节数统计方案

要准确统计WebSocket实际通过网络发送的字节数,确实不能直接在send()调用后累加数据长度——正如你所说,send()只是把数据加入发送队列,返回时数据还没真正发出去。而死循环轮询bufferedAmount的方式会阻塞主线程,影响性能,显然不可取。

目前WebSocket API没有提供直接的"数据发送完成"事件,不过可以通过bufferedAmount属性结合非阻塞的检查逻辑来实现准确统计,下面是具体方案:

核心思路

维护一个待确认发送的队列,每次调用send()时,记录当前的bufferedAmount和要发送的数据长度;然后通过requestAnimationFrame(或低频率的setTimeout)周期性检查bufferedAmount的变化,当bufferedAmount降到小于等于发送前的数值时,说明该数据块已经完全发送出去,此时再累加字节数。

代码实现

let bytesSent = 0;
// 存储待确认的发送任务:{ dataLength: 字节数, preSendBuffered: 发送前的bufferedAmount }
const pendingSends = [];

function sendAndTrack(webSocket, data) {
  const dataLength = data.length;
  const preSendBuffered = webSocket.bufferedAmount;
  
  webSocket.send(data);
  pendingSends.push({ dataLength, preSendBuffered });
  
  // 启动检查逻辑
  checkPendingSends(webSocket);
}

function checkPendingSends(webSocket) {
  let index = 0;
  while (index < pendingSends.length) {
    const task = pendingSends[index];
    // 当当前bufferedAmount小于等于发送前的数值,说明该数据已发送完成
    if (webSocket.bufferedAmount <= task.preSendBuffered) {
      bytesSent += task.dataLength;
      // 从队列中移除已完成的任务
      pendingSends.splice(index, 1);
    } else {
      index++;
    }
  }
  
  // 如果还有待确认任务,继续下一轮检查
  if (pendingSends.length > 0) {
    requestAnimationFrame(() => checkPendingSends(webSocket));
  }
}

方案优势

  1. 非阻塞:用requestAnimationFrame替代死循环轮询,只会在浏览器重绘间隙执行检查,不会阻塞主线程,对性能影响极小。
  2. 准确性:通过对比发送前后的bufferedAmount,能精准判断单个数据块是否已发送完成。
  3. 可扩展:队列结构支持批量发送场景,能同时跟踪多个待确认的发送任务。

补充说明

如果你的场景对统计精度要求不是极高(比如允许少量延迟统计),也可以监听bufferedamountlow事件:

webSocket.bufferedAmountLowThreshold = 0;
webSocket.addEventListener('bufferedamountlow', () => {
  // 此时队列中待发送的数据已全部发完,可以累加之前记录的所有待统计字节数
  // 注意:这种方式适合批量统计,无法精准对应单个send操作
});

不过这种方式只能知道队列清空的时机,无法精确对应每一次send的数据块,所以队列跟踪的方案更适合需要精准统计的场景。

内容的提问来源于stack exchange,提问作者Roj

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 15:35:05