使用Indy的TIdFTPServer统计展示客户端上传下载的流量比特率汇总
实现TIdFTPServer全局流量比特率统计方案
核心实现逻辑
TIdFTPServer 本身未提供全局流量统计的内置接口,需要通过监听传输事件累加字节计数,再按时间窗口计算比特率。由于服务端每个客户端连接都运行在独立子线程,所有统计变量的读写都需要加锁保证线程安全。
步骤1:定义统计相关变量(Delphi示例)
在主窗口类中定义64位统计变量、线程锁和计时基准值:
private // 累计总上传字节数 FTotalUploadBytes: Int64; // 累计总下载字节数 FTotalDownloadBytes: Int64; // 上一次计算比特率的时间戳 FLastCalcTime: TDateTime; // 上一次计算比特率时的总传输字节数 FLastTotalBytes: Int64; // 当前总比特率(单位bps) FCurrentBitrate: Int64; // 线程安全锁 FStatCrit: TCriticalSection;
步骤2:绑定传输事件并累加字节数
绑定TIdFTPServer的OnTransfer事件,每次传输数据块时累加对应统计值:
procedure TMainForm.FormCreate(Sender: TObject); begin FStatCrit := TCriticalSection.Create; FTotalUploadBytes := 0; FTotalDownloadBytes := 0; FLastCalcTime := Now; FLastTotalBytes := 0; // 绑定传输事件回调 IdFTPServer1.OnTransfer := FTPTransferCallback; end; procedure TMainForm.FTPTransferCallback(AContext: TIdContext; ATransfer: TIdFTPTransfer; ABuffer: TBytes; ACount: Integer); begin FStatCrit.Enter; try case ATransfer.Operation of ftpStore: Inc(FTotalUploadBytes, ACount); // 客户端上传 ftpRetrieve: Inc(FTotalDownloadBytes, ACount); // 客户端下载 end; finally FStatCrit.Leave; end; end;
步骤3:定时计算比特率并更新界面
添加TTimer组件,设置更新间隔为1000ms,在定时器回调中计算比特率并更新UI:
procedure TMainForm.StatUpdateTimerTimer(Sender: TObject); var LNow: TDateTime; LTimeDiffSec: Double; LTotalBytesNow: Int64; LBytesDelta: Int64; begin FStatCrit.Enter; try LNow := Now; LTotalBytesNow := FTotalUploadBytes + FTotalDownloadBytes; LTimeDiffSec := SecondsBetween(LNow, FLastCalcTime); if LTimeDiffSec > 0 then begin LBytesDelta := LTotalBytesNow - FLastTotalBytes; // 字节转比特:1字节=8比特 FCurrentBitrate := Round(LBytesDelta * 8 / LTimeDiffSec); // 更新界面显示 lblUploadTotal.Caption := Format('累计上传:%s', [FormatFileSize(FTotalUploadBytes)]); lblDownloadTotal.Caption := Format('累计下载:%s', [FormatFileSize(FTotalDownloadBytes)]); lblTotalBitrate.Caption := Format('当前总比特率:%.2f Mbps', [FCurrentBitrate / 1024 / 1024]); // 更新统计基准值 FLastCalcTime := LNow; FLastTotalBytes := LTotalBytesNow; end; finally FStatCrit.Leave; end; end;
注意事项
- 必须使用64位整数存储统计值,避免大流量场景下32位整数溢出
- 所有对统计变量的读写操作都要加锁,避免多线程并发访问导致的数据异常
- 比特率更新间隔建议设置为1~2秒,过短的更新间隔会带来不必要的性能开销
- C++ Builder 实现逻辑完全一致,仅语法有差异
内容的提问来源于stack exchange,提问作者Денис Бердяев
相关产品推荐
相关产品推荐

