【腾讯犀牛鸟计划】体验trpc http流式服务开发 #222
Open
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
代码体验报告:基于 tRPC 的文件传输增强功能开发
一、项目概述
项目名称:tRPC 文件传输增强模块
开发时间:2025年7月
开发工具/语言:C++
项目目标:在学习和使用 tRPC 的基础上,扩展实现文件上传/下载功能,支持进度条显示、SHA256 校验、多文件流处理、限速下载等,提高文件传输的可靠性与用户体验。
二、开发环境
操作系统:ubuntu22.04
编程语言及版本:C++17
使用的框架/库:
tRPC
picosha2.h(用于 C++ 端 SHA256 哈希计算)
其他工具:
VS Code
三、功能实现
✅ 文件上传下载统计可视化功能
*在上传或下载过程中,实时显示进度条,提升用户体验
*在上传完成时自动记录总耗时与平均速率
*使用 C++ 构建控制台进度条,适用于服务端日志或 CLI 工具
✅ SHA256 校验(使用 picosha2.h)
*在 C++ 模块中集成 picosha2.h 实现高效哈希计算
*确保文件上传/下载过程中的完整性,防止传输数据被篡改或破损
📥 计算 SHA256(文件端)
📤 服务端添加 SHA256 校验头
📦 客户端下载后进行校验
用户可选择是否启用本地校验,通过 FLAGS_enable_download_hash 控制
✅ 限速下载
*控制下载速率,避免服务端带宽过载,同时为用户提供平稳的传输体验。
通过记录发送数据的时间和字节数,动态计算实际传输速率,并在必要时引入延迟(sleep)控制发送速率不超过设定阈值。
设置 constexpr std::size_t rate_limit_bytes_per_sec = 900 * 1024; // 512KB/s
✅ 文件流式多文件传输(Streaming Multi-File Transfer)
*流式读取:使用 std::ifstream 按块读取,适合大文件处理
*逐个发送文件:每个文件构造独立的 header(包含文件名、大小、hash),确保接收端可以识别和校验
*边读取边发送:不加载整个文件到内存,避免资源占用过高,适合多大文件连续传输
*封装结构体头部:通过 FileSegmentHeader 发送结构化元信息,利于客户端解析与验证
*非阻塞串流发送:利用 writer.Write(...) 实现异步非阻塞写入到流通道
🧩 多文件识别与调度
🚚 多文件发送核心代码
📦 FileSegmentHeader 示例结构说明
四、开发过程体验
🧩 遇到的问题及解决方案
🧨 问题表现
服务端或客户端写入文件后立即调用 CalculateSHA256() 校验文件内容
获取到的哈希值与期望值不匹配(即使文件名和大小相同)
🎯 原因分析
文件流(如 std::ofstream fout)在写入时使用缓冲机制。如果未主动刷新或关闭,部分数据可能仍停留在缓冲区,尚未写入磁盘 。
调用 CalculateSHA256() 时读取的是磁盘文件内容,如果未 flush,会导致读取数据不完整,从而哈希值错误。
✅ 解决办法
在文件写入完成后,务必执行如下操作:
调用 CalculateSHA256() 校验之前,确保文件已完全写入磁盘。
2.添加限速下载 客户端出现超时
🧨 问题表现
客户端下载添加如下代码,定位问题。
🎯 原因分析
在调试过程中,发现客户端在 stream.Read() 时长时间阻塞,怀疑与服务端限速策略有关。为验证和规避这一问题,查阅了 HttpReadStream 的流式同步接口文档,发现其支持以下两种读取方式:
HttpReadStream 流式同步接口列表
Status Read(NoncontiguousBuffer& item, size_t max_bytes)
max_bytes
:读取字节数,如果剩余内容不足则立即返回并标识 EOFStatus
Status Read(NoncontiguousBuffer& item, size_t max_bytes, const std::chrono::time_point<Clock, Dur>& expiry)
expiry
:如trpc::ReadSteadyClock() + std::chrono::milliseconds(3)
Status
对比后采用了第二种接口形式,明确设置了读取操作的超时时间点,有效防止了长期阻塞。最终代码调整如下:
通过配合 status.ToString().find("timeout") 的判断,实现了对限速场景的优雅处理,客户端逻辑更加健壮稳定。
✅ 解决办法
添加:status = stream.Read(buffer, kBufferSize, std::chrono::seconds(3));