尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

流量监控前端不显示问题

流量监控前端不显示问题
📅 发布时间:2026/6/19 0:00:41

现象描述

前端界面显示上下行速率有问题,明明有流量,有时候是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) {

相关新闻

  • 利用Proxifier、Burp Suite和亮数据高效抓包
  • C语言:枚举体
  • 【LLM基础教程】语言模型基础

最新新闻

  • 2026海口名表回收行情解析!哪些款式保值抗跌?避坑指南速看 - 奢品小当家
  • Moteus:当开源精神遇见高性能无刷伺服控制
  • 2026年6月卧式潜水泵厂家推荐 - 多才菠萝
  • 2026 桂林防水补漏靠谱服务商盘点:屋面 / 厨卫 / 外墙 / 地下室渗水维修详解,适配桂北喀斯特山水防潮防水甄选指南 - 宅安选房屋修缮
  • 题解:P16881 [GKS 2022 #D] Image Labeler
  • 微积分基石:从连续、可导到洛必达法则,厘清概念差异与实战边界

日新闻

  • 5分钟掌握Python进化算法:Geatpy高性能优化工具完全指南
  • Microchip 24AA044 EEPROM选型与应用全指南:从参数解析到实战编程
  • 华为的鸿蒙到底有多牛?为什么称作遥遥领先?

周新闻

  • 3步解锁iOS设备:applera1n激活锁绕过完全指南
  • 39 2026 人工智能证书终极盘点,普通人选 AI 证书可以从这些方向入手
  • Redis 暴露公网有多危险?从端口检查到补救步骤

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号