0

0

如何使用c++和gRPC实现流式(streaming) RPC? (双向通信)

穿越時空

穿越時空

发布时间:2026-01-22 14:24:02

|

922人浏览过

|

来源于php中文网

原创

gRPC双向流(Bidi Streaming)支持客户端与服务器在单个RPC中同时异步收发多条消息,需在.proto中声明双stream,用async C++ API配合CompletionQueue手动管理读写协程及回调,漏调Read()或Write()将导致流停滞。

如何使用c++和grpc实现流式(streaming) rpc? (双向通信)

什么是 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_ → 写入失败被忽略

服务端如何响应并维持双向流

服务端用 AsyncServiceRequestChat() 接收新流,拿到 ServerAsyncReaderWriter 对象后,必须立刻调用其 Read() 启动接收,再根据业务逻辑决定何时 Write()。注意:所有 Read()/Write() 都是异步且需配对回调,不能在回调里直接阻塞等待另一端。

松果AI写作
松果AI写作

专业全能的高效AI写作工具

下载

立即学习C++免费学习笔记(深入)”;

  • 不要在 OnReadDone() 回调里直接调用 Write() 并期望立刻发出——必须再次 Write() + Next() 才生效
  • 若需广播消息(如聊天室),要把 ServerAsyncReaderWriter 指针安全存入容器,但注意生命周期:客户端断连时该对象会被销毁,需监听 Finish() 状态
  • 性能陷阱:频繁小包 Write() 会放大 TCP 小包问题,可考虑缓冲+定时 flush,但需权衡延迟
  • 调试提示:抓包看 HTTP/2 DATA 帧是否双向持续流动;若只有 client→server 有数据,大概率是 server 忘了 Read()Write() 没触发完成队列

双向流的本质不是“自动管道”,而是由你手动拼接的一组异步读写原语——漏掉一次 Read(),整个流就静默了。最易错的永远是“以为发完就完了”,其实只是刚开了个门。

相关文章

c++速学教程(入门到精通)
c++速学教程(入门到精通)

c++怎么学习?c++怎么入门?c++在哪学?c++怎么学才快?不用担心,这里为大家提供了c++速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
javascriptvoid(o)怎么解决
javascriptvoid(o)怎么解决

javascriptvoid(o)的解决办法:1、检查语法错误;2、确保正确的执行环境;3、检查其他代码的冲突;4、使用事件委托;5、使用其他绑定方式;6、检查外部资源等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

175

2023.11.23

java中void的含义
java中void的含义

本专题整合了Java中void的相关内容,阅读专题下面的文章了解更多详细内容。

97

2025.11.27

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

1049

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

86

2025.10.17

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

456

2025.12.29

java接口相关教程
java接口相关教程

本专题整合了java接口相关内容,阅读专题下面的文章了解更多详细内容。

11

2026.01.19

http500解决方法
http500解决方法

http500解决方法有检查服务器日志、检查代码错误、检查服务器配置、检查文件和目录权限、检查资源不足、更新软件版本、重启服务器或寻求专业帮助等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

378

2023.11.09

http请求415错误怎么解决
http请求415错误怎么解决

解决方法:1、检查请求头中的Content-Type;2、检查请求体中的数据格式;3、使用适当的编码格式;4、使用适当的请求方法;5、检查服务器端的支持情况。更多http请求415错误怎么解决的相关内容,可以阅读下面的文章。

413

2023.11.14

Golang 性能分析与pprof调优实战
Golang 性能分析与pprof调优实战

本专题系统讲解 Golang 应用的性能分析与调优方法,重点覆盖 pprof 的使用方式,包括 CPU、内存、阻塞与 goroutine 分析,火焰图解读,常见性能瓶颈定位思路,以及在真实项目中进行针对性优化的实践技巧。通过案例讲解,帮助开发者掌握 用数据驱动的方式持续提升 Go 程序性能与稳定性。

1

2026.01.22

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C# 教程
C# 教程

共94课时 | 7.2万人学习

C 教程
C 教程

共75课时 | 4.1万人学习

C++教程
C++教程

共115课时 | 13.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号