如何使用c++和gRPC实现流式(streaming) RPC? (双向通信)
发布时间 - 2026-01-22 00:00:00 点击率:次gRPC双向流(Bidi Streaming)支持客户端与服务器在单个RPC中同时异步收发多条消息,需在.proto中声明双stream,用async C++ API配合CompletionQueue手动管理读写协程及回调,漏调Read()或Write()将导致流停滞。
什么是 gRPC 双向流(Bidi Streaming)
gRPC 双向流 RPC 允许客户端和服务器在同一个 RPC 调用中**同时发送和接收多个消息**,连接保持打开,直到任意一方关闭。它对应 Protocol Buffer 中的 stream 关键字出现在请求和响应两侧:rpc Chat(stream ChatMessage) returns (stream ChatMessage);。这不是“先发后收”或“发一次收多次”,而是真正的并发读写——你得自己管理读/写协程或回调,否则容易卡死。
如何定义并生成双向流接口
关键在 .proto 文件里声明双 stream,且必须用 async C++ API(同步 API 不支持双向流)。生成代码时需启用 C++ 插件,并确保 grpc_cpp_plugin 版本与 libgrpc 匹配,否则 AsyncReaderWriter 类型可能缺失或签名不一致。
- 定义示例:
service ChatService { rpc Chat(stream ChatMessage) returns (stream ChatMessage); } message ChatMessage { string content = 1; int64 timestamp = 2; } - 生成命令要包含
--grpc_out和--plugin=protoc-gen-grpc=.../grpc_cpp_plugin - 生成后你会得到
ChatService::AsyncService和客户端 stub 的AsyncChat方法,返回类型是std::unique_ptr<:clientasyncreaderwriter chatmessage>>
客户端如何发起并驱动双向流
客户端必须显式启动读写循环:先调用 Write() 发送首条消息(或空消息触发流建立),再立即调用 Read() 启动异步接收;后续靠 OnReadDone() 和 OnWriteDone() 回调交替推进。漏掉任一 Read() 或重复 Write() 而没等完成,都会导致流挂起或崩溃。
- 必须用
CompletionQueue驱动异步事件,不能混用多个队列处理同一 stream -
Write()第二个参数是void*标签,用于区分不同操作;建议用this或枚举值,避免裸指针误释放 - 调用
WritesDone()表示客户端不再发消息,但服务端仍可继续发;之后收到status.ok() == true且无更多Read()时才算真正结束 - 常见错误:
Read()后没再调用下一次Read()→ 流停滞;Write()前未检查write_ok_→ 写入失败被忽略
服务端如何响应并维持双向流
服务端用 AsyncService 的 RequestChat() 接收新流,拿到 ServerAsyncReaderWriter 对象后,必须立刻调用其 Read() 启动接收,再根据业务逻辑决定何时 Write()。注意:所有 Read()/Write() 都是异步

- 不要在
OnReadDone()回调里直接调用Write()并期望立刻发出——必须再次Write()+Next()才生效 - 若需广播消息(如聊天室),要把
ServerAsyncReaderWriter指针安全存入容器,但注意生命周期:客户端断连时该对象会被销毁,需监听Finish()状态 - 性能陷阱:频繁小包
Write()会放大 TCP 小包问题,可考虑缓冲+定时 flush,但需权衡延迟 - 调试提示:抓包看 HTTP/2 DATA 帧是否双向持续流动;若只有 client→server 有数据,大概率是 server 忘了
Read()或Write()没触发完成队列
双向流的本质不是“自动管道”,而是由你手动拼接的一组异步读写原语——漏掉一次 Read(),整个流就静默了。最易错的永远是“以为发完就完了”,其实只是刚开了个门。
# c++
# stream
# void
# 循环
# 指针
# 接口
# 并发
# 对象
# 事件
# this
# 异步
# http
# rpc
# 客户端
# 回调
# 服务端
# 多个
# 都是
# 你会
# 出现在
# 能在
# 要把
# 第二个
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
高端云建站费用究竟需要多少预算?
湖南网站制作公司,湖南上善若水科技有限公司做什么的?
如何安全更换建站之星模板并保留数据?
Win11怎么更改系统语言为中文_Windows11安装语言包并设为显示语言
Win11关机界面怎么改_Win11自定义关机画面设置【工具】
简单实现Android验证码
香港服务器网站搭建教程-电商部署、配置优化与安全稳定指南
Win11怎么查看显卡温度 Win11任务管理器查看GPU温度【技巧】
Laravel怎么使用Intervention Image库处理图片上传和缩放
如何将凡科建站内容保存为本地文件?
zabbix利用python脚本发送报警邮件的方法
实例解析angularjs的filter过滤器
Laravel怎么导出Excel文件_Laravel Excel插件使用教程
详解免费开源的DotNet二维码操作组件ThoughtWorks.QRCode(.NET组件介绍之四)
如何解决hover在ie6中的兼容性问题
北京网站制作公司哪家好一点,北京租房网站有哪些?
如何彻底删除建站之星生成的Banner?
CSS3怎么给轮播图加过渡动画_transition加transform实现【技巧】
如何在搬瓦工VPS快速搭建网站?
如何快速查询域名建站关键信息?
SQL查询语句优化的实用方法总结
Gemini手机端怎么发图片_Gemini手机端发图方法【步骤】
如何用好域名打造高点击率的自主建站?
如何自定义safari浏览器工具栏?个性化设置safari浏览器界面教程【技巧】
如何用5美元大硬盘VPS安全高效搭建个人网站?
品牌网站制作公司有哪些,买正品品牌一般去哪个网站买?
Laravel怎么实现前端Toast弹窗提示_Laravel Session闪存数据Flash传递给前端【方法】
C++时间戳转换成日期时间的步骤和示例代码
如何在阿里云购买域名并搭建网站?
android nfc常用标签读取总结
Laravel事件和监听器如何实现_Laravel Events & Listeners解耦应用的实战教程
活动邀请函制作网站有哪些,活动邀请函文案?
Linux系统运维自动化项目教程_Ansible批量管理实战
电商网站制作多少钱一个,电子商务公司的网站制作费用计入什么科目?
python中快速进行多个字符替换的方法小结
详解MySQL数据库的安装与密码配置
微信公众帐号开发教程之图文消息全攻略
微信小程序 wx.uploadFile无法上传解决办法
,南京靠谱的征婚网站?
jQuery validate插件功能与用法详解
如何破解联通资金短缺导致的基站建设难题?
如何用AI帮你把自己的生活经历写成一个有趣的故事?
公司网站制作需要多少钱,找人做公司网站需要多少钱?
标题:Vue + Vuex + JWT 身份认证的正确实践与常见误区解析
Laravel如何实现一对一模型关联?(Eloquent示例)
如何在IIS中新建站点并解决端口绑定冲突?
如何续费美橙建站之星域名及服务?
Windows10电脑怎么查看硬盘通电时间_Win10使用工具检测磁盘健康
打造顶配客厅影院,这份100寸电视推荐名单请查收
太平洋网站制作公司,网络用语太平洋是什么意思?

