当前位置: 首页 > news >正文

流量监控前端不显示问题

现象描述

前端界面显示上下行速率有问题,明明有流量,有时候是0有时候有数字。

通过接口定位到以下代码:

.h文件

#ifndef __TRAN_MONITOR__ #define __TRANS_MONITOR__ #include "hv/HttpServer.h" int NetSpeedMonitor_Init(const std::string &usbname); hv::Json UpDownloadGet(); #endif

Cpp文件:

#include <iostream> #include <stdio.h> #include <fstream> #include <thread> #include <chrono> #include <sys/stat.h> #include "Comport/TransMonitor.h" #include "hv/hlog.h" #include "hv/HttpServer.h" using namespace std; string upload_speed = "0 bytes/s"; // ❗❗❗❗❗❗❗❗❗❗后台线程不停写,HTTP线程不停读,没有mutex,没有atomic,没有内存屏障 string download_speed = "0 bytes/s"; // ❗❗❗❗❗❗❗❗❗❗导致:读到旧值,空字符串,读到一半的内容 static bool directoryExists(const string& path) { struct stat info; return stat(path.c_str(), &info) == 0 && S_ISDIR(info.st_mode); } static void readNetworkStatistics(const string &usbname) { const string basePath = "/sys/class/net/" + usbname + "/statistics/"; uint64_t prevRxBytes = 0, prevTxBytes = 0; while(true) { if (directoryExists(basePath)) { ifstream rxFile(basePath + "rx_bytes"); ifstream txFile(basePath + "tx_bytes"); uint64_t rxBytes = 0, txBytes = 0; char upspeed[32]; char downspeed[32]; if (rxFile >> rxBytes && txFile >> txBytes) { uint64_t rxDiff = rxBytes - prevRxBytes; // ❗❗❗❗❗❗❗计算的不是速率,只是差值❗❗❗❗❗❗❗❗❗❗ uint64_t txDiff = txBytes - prevTxBytes; //❗❗❗❗❗❗❗第一次diff极大,之后立刻归零❗❗❗❗❗❗❗ string rxUnit = "bytes/s", txUnit = "bytes/s"; double rxValue = rxDiff, txValue = txDiff; if (rxDiff > 1024) { // ❗❗❗❗❗❗❗❗❗❗1.两个 if 都会进l,前面的 KB 计算被后面的 MB 覆盖,逻辑可读性极差,不工程化 rxValue = static_cast<double>(rxDiff) / 1024; rxUnit = "KB/s"; } if (txDiff > 1024) { txValue = static_cast<double>(txDiff) / 1024; txUnit = "KB/s"; } if (rxDiff > 1024 * 1024) { // 2 rxValue = static_cast<double>(rxDiff) / (1024 * 1024); rxUnit = "MB/s"; } if (txDiff > 1024 * 1024) { txValue = static_cast<double>(txDiff) / (1024 * 1024); txUnit = "MB/s"; } if(txValue < 0) txValue = 0; if(rxValue < 0) rxValue = 0; sprintf(upspeed, "%.2f %s", txValue, txUnit.c_str()); sprintf(downspeed, "%.2f %s", rxValue, rxUnit.c_str()); upload_speed = upspeed; download_speed = downspeed; prevRxBytes = rxBytes; prevTxBytes = txBytes; } else { hloge("Read error at network transfer speed"); } rxFile.close(); txFile.close(); } else { sleep(5); } sleep(1); // ❗❗❗❗❗❗❗❗❗❗Linux sleep(1):≥1 秒 } } int NetSpeedMonitor_Init(const std::string &usbname) { thread networkThread(readNetworkStatistics, usbname); networkThread.detach(); return 0; } hv::Json UpDownloadGet() { hv::Json j; j["upstream"] = upload_speed; // ❗❗❗❗❗❗❗❗❗❗后端不建议返回字符串速率 j["downstream"] = download_speed; return j; }

看代码后问题显而易见:

只有在以下条件同时满足时,才会看到非 0:

  • 网卡此刻刚好有流量

  • 线程刚好按近似 1 秒跑

  • HTTP 线程刚好没读到写一半的 string

在demo里能跑,但是在生产环境必出问题。

解决问题

#include <iostream> #include <stdio.h> #include <fstream> #include <thread> #include <chrono> #include <sys/stat.h> #include "Comport/TransMonitor.h" #include "hv/hlog.h" #include "hv/HttpServer.h" #include <atomic> using namespace std; static std::atomic<uint64_t> g_rx_bps{0}; static std::atomic<uint64_t> g_tx_bps{0}; static void readNetworkStatistics(const string& ifname) { const string base = "/sys/class/net/" + ifname + "/statistics/"; uint64_t prevRx = 0, prevTx = 0; auto prevTime = chrono::steady_clock::now(); while (true) { ifstream rx(base + "rx_bytes"); ifstream tx(base + "tx_bytes"); uint64_t rxBytes = 0, txBytes = 0; if (!(rx >> rxBytes && tx >> txBytes)) { sleep(1); continue; } auto now = chrono::steady_clock::now(); double seconds = chrono::duration_cast<chrono::milliseconds>(now - prevTime).count() / 1000.0; if (prevRx != 0 && seconds > 0.2) { g_rx_bps = (rxBytes - prevRx) / seconds; g_tx_bps = (txBytes - prevTx) / seconds; } prevRx = rxBytes; prevTx = txBytes; prevTime = now; sleep(1); } } int NetSpeedMonitor_Init(const std::string &usbname) { thread networkThread(readNetworkStatistics, usbname); networkThread.detach(); return 0; } static std::string formatSpeed(uint64_t bps) { char buf[32]; if (bps < 1024) { snprintf(buf, sizeof(buf), "%lu B/s", bps); } else if (bps < 1024 * 1024) { snprintf(buf, sizeof(buf), "%.2f KB/s", bps / 1024.0); } else { snprintf(buf, sizeof(buf), "%.2f MB/s", bps / (1024.0 * 1024.0)); } return std::string(buf); } hv::Json UpDownloadGet() { uint64_t tx = g_tx_bps.load(); uint64_t rx = g_rx_bps.load(); hv::Json j; j["upstream"] = formatSpeed(tx); j["downstream"] = formatSpeed(rx); return j; }

1.atomic<uint64_t>存速率,避免了 string 竞争,HTTP线程读安全,后台线程安全

static std::atomic<uint64_t> g_rx_bps{0}; static std::atomic<uint64_t> g_tx_bps{0};

2.steady_clock+ 时间差算速率,不依赖sleep(1)精度,线程调度抖动不会把速率压成 0

double seconds = chrono::duration_cast<chrono::milliseconds>(now - prevTime).count() / 1000.0;

3.第一次采样不算速率,避免第一次巨大 diff,避免刚启动速率乱跳

if (prevRx != 0 && seconds > 0.2) {
http://www.rkmt.cn/news/110637.html

相关文章:

  • 利用Proxifier、Burp Suite和亮数据高效抓包
  • C语言:枚举体
  • 【LLM基础教程】语言模型基础
  • YOLO-v5论文的10个核心创新点解析
  • 【LLM基础教程】统计语言模型N-gram
  • Nigx配置
  • gpt-oss-20b RESTful API设计与集成指南
  • 【玩转全栈】----Django根本设置和介绍
  • GPT-SoVITS音色相似度优化技巧:提升克隆真实感
  • 2025/12/16英语打卡
  • Windows下Python安装失败?换用清华源重试TensorFlow安装
  • Qwen3-32B大模型调用与鉴权指南
  • 2025年十大隐形车衣优质厂家排行榜,隐形车衣厂家测评指南 - myqiye
  • HuggingFace镜像网站推荐列表(国内可用)
  • DiskInfo下载官网替代方案:高效获取YOLO资源
  • SQL条件中WHERE 1=1 的功能
  • 职业本科与高职专科低空专业就业方向具体区别
  • Langchain-Chatchat能否导出问答记录?
  • vLLM 0.11.0 发布:全面移除 V0 引擎,性能与多模态支持再升级
  • 91n推荐:最适合生产环境的TensorRT镜像部署方式
  • MIL-STD-1553B总线仿真应用解析
  • 题目:字符串逆序
  • Conda-forge构建SD3.5 FP8推理环境的正确姿势
  • 45、Linux系统使用指南:文件、多媒体与网络操作全解析
  • 零基础部署Wan2.2-T2V-A14B:本地化视频生成全指南
  • 告别听不清困境,声网STT让每一次沟通都被精准捕捉
  • Fifth Assignment——Alpha Sprint
  • 机房预约系统
  • PCB打板是否需要SMT贴片?——从工程实战角度看清本质
  • “AI招聘 潮头之上”,2025NFuture 最佳雇主颁奖盛典上海站圆满落幕