场景

gPRC简介以及Java中使用gPRC实现客户端与服务端通信(附代码下载):

https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/108711541

在上面的博客中介绍了gRPC以及使用最基本的rpc通信方式即一个请求对象返回一个响应的方式进行通信。

除此之外gRPC还有以下三种方式。

服务端流式

一个请求对象,服务端返回多个结果对象

proto示例语法

rpc GetStudentsByAge(StudentRequest) returns (stream StudentResponse) {}

客户端流式

客户端传入多个请求对象,服务端返回一个响应结果。

proto示例语法

rpc GetStudentsWrapperByAges(stream StudentRequest) returns (StudentResponseList) {}

双向流式

传入多个对象可以返回多个响应对象

注:

博客:
https://blog.csdn.net/badao_liumang_qizhi
关注公众号
霸道的程序猿
获取编程相关电子书、教程推送与免费下载。

实现

服务端流式实现

在上面博客的基础上,打开Person.proto文件

message StudentRequest {int32 age = 1;
}message StudentResponse {string name = 1;int32 age = 2;string city = 3;
}

添加两个message作为请求和响应对象。

因为gRPC的请求和响应对象必须在message中定义,不能直接使用string或者int32这种作为参数。

然后在新建接口方法

service PersonService {rpc GetStudentsByAge(StudentRequest) returns (stream StudentResponse) {}
}

此方法是要请求参数为一个age,然后返回多个学生对象。

然后调用插件生成代码。

然后来到PersonServiceImpl中对接口方法进行实现

    @Overridepublic void getStudentsByAge(StudentRequest request, StreamObserver<StudentResponse> responseObserver) {System.out.println("接收到的客户端消息为:"+request.getAge());responseObserver.onNext(StudentResponse.newBuilder().setName("1公众号:霸道的程序猿").setAge(30).setCity("北京").build());responseObserver.onNext(StudentResponse.newBuilder().setName("2公众号:霸道的程序猿").setAge(40).setCity("上海").build());responseObserver.onNext(StudentResponse.newBuilder().setName("3公众号:霸道的程序猿").setAge(50).setCity("广州").build());responseObserver.onCompleted();}

然后来到客户端中

        ManagedChannel managedChannel  = ManagedChannelBuilder.forAddress("localhost",8899).usePlaintext().build();PersonServiceGrpc.PersonServiceBlockingStub blockingStub = PersonServiceGrpc.newBlockingStub(managedChannel);System.out.println("请求-流式响应,调用getRealNameByUsername");Iterator<StudentResponse> iter = blockingStub.getStudentsByAge(StudentRequest.newBuilder().setAge(20).build());while (iter.hasNext()){StudentResponse studentResponse = iter.next();System.out.println(studentResponse.getName());System.out.println(studentResponse.getAge());System.out.println(studentResponse.getCity());}

然后运行服务端后再运行客户端

此时服务端

客户端流式实现

打开proto文件

message StudentRequest {int32 age = 1;
}message StudentResponse {string name = 1;int32 age = 2;string city = 3;
}message StudentResponseList {repeated StudentResponse studentResponse = 1;
}

添加响应的list,要实现客户端发动流式多个请求参数(年龄),服务端返回单个list对象,其中每个List的数据是学生对象。

添加接口方法

service PersonService {rpc GetStudentsWrapperByAges(stream StudentRequest) returns (StudentResponseList) {}
}

然后调用插件生成代码。打开PersonServiceImpl进行方法的实现

    @Overridepublic StreamObserver<StudentRequest> getStudentsWrapperByAges(final StreamObserver<StudentResponseList> responseObserver) {return new StreamObserver<StudentRequest>() {public void onNext(StudentRequest studentRequest) {System.out.println("onNext:"+studentRequest.getAge());}public void onError(Throwable throwable) {System.out.println(throwable.getMessage());}public void onCompleted() {StudentResponse studentResponse = StudentResponse.newBuilder().setName("公众号:霸道的程序猿").setAge(20).setCity("北京").build();StudentResponse studentResponse1 = StudentResponse.newBuilder().setName("1公众号:霸道的程序猿").setAge(30).setCity("上海").build();StudentResponseList studentResponseList = StudentResponseList.newBuilder().addStudentResponse(studentResponse).addStudentResponse(studentResponse1).build();responseObserver.onNext(studentResponseList);responseObserver.onCompleted();}};}

与上面不同,客户端如果是流式请求的话,那么客户端必须使用异步的stub

PersonServiceGrpc.PersonServiceStub stub = PersonServiceGrpc.newStub(managedChannel);

客户端代码为

        ManagedChannel managedChannel  = ManagedChannelBuilder.forAddress("localhost",8899).usePlaintext().build();PersonServiceGrpc.PersonServiceStub stub = PersonServiceGrpc.newStub(managedChannel);System.out.println("-----------------------------");System.out.println("流式请求-响应,调用GetStudentsWrapperByAges");StreamObserver<StudentResponseList> studentResponseListStreamObserver = new StreamObserver<StudentResponseList>() {public void onNext(StudentResponseList studentResponseList) {studentResponseList.getStudentResponseList().forEach(studengResponse ->{System.out.println(studengResponse.getName());System.out.println(studengResponse.getAge());System.out.println(studengResponse.getCity());});}public void onError(Throwable throwable) {System.out.println(throwable.getMessage());}public void onCompleted() {System.out.println("completed");}};StreamObserver<StudentRequest> studentRequestStreamObserver = stub.getStudentsWrapperByAges(studentResponseListStreamObserver);studentRequestStreamObserver.onNext(StudentRequest.newBuilder().setAge(20).build());studentRequestStreamObserver.onNext(StudentRequest.newBuilder().setAge(30).build());studentRequestStreamObserver.onNext(StudentRequest.newBuilder().setAge(40).build());studentRequestStreamObserver.onCompleted();try {Thread.sleep(50000);} catch (InterruptedException e) {e.printStackTrace();}

因为是异步的所以必须使进程进行休眠才能看到效果

运行服务端后运行客户端

此时服务端

双向流式实现

打开proto文件

message StreamRequest {string request_info = 1;
}message StreamResponse {string response_info = 1;
}

新建流式请求与响应参数,然后新建接口方法

service PersonService {rpc BiTalk(stream StreamRequest) returns (stream StreamResponse) {}
}

然后实现接口方法

    @Overridepublic StreamObserver<StreamRequest> biTalk(StreamObserver<StreamResponse> responseObserver) {return new StreamObserver<StreamRequest>() {@Overridepublic void onNext(StreamRequest streamRequest) {System.out.println(streamRequest.getRequestInfo());responseObserver.onNext(StreamResponse.newBuilder().setResponseInfo(UUID.randomUUID().toString()).build());}@Overridepublic void onError(Throwable throwable) {System.out.println(throwable.getMessage());}@Overridepublic void onCompleted() {responseObserver.onCompleted();}};}

在客户端中

package com.badao.grpcjava;import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.stub.StreamObserver;import java.time.LocalDate;
import java.util.Iterator;public class GrpcClient {public static void main(String[] args) {ManagedChannel managedChannel  = ManagedChannelBuilder.forAddress("localhost",8899).usePlaintext().build();PersonServiceGrpc.PersonServiceStub stub = PersonServiceGrpc.newStub(managedChannel);System.out.println("-----------------------------");System.out.println("流式请求-流式响应,调用BiTalk");StreamObserver<StreamRequest> requestStreamObserver = stub.biTalk(new StreamObserver<StreamResponse>() {@Overridepublic void onNext(StreamResponse streamResponse) {System.out.println(streamResponse.getResponseInfo());}@Overridepublic void onError(Throwable throwable) {System.out.println(throwable.getMessage());}@Overridepublic void onCompleted() {System.out.println("onComplated");}});for(int i =0;i<10;i++){requestStreamObserver.onNext(StreamRequest.newBuilder().setRequestInfo(LocalDate.now().toString()).build());try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}try {Thread.sleep(50000);} catch (InterruptedException e) {e.printStackTrace();}}
}

运行服务端后运行客户端

示例代码下载

https://download.csdn.net/download/BADAO_LIUMANG_QIZHI/12883063

gRPC的通信方式-客户端流式、服务端流式、双向流式在Java的调用示例相关推荐

  1. grpc 客户端的context 服务端获取不到_MLamp;DEV[10] | gRPC的应用

    上一期和大家谈到了gRPC的快速开始,我么哪知道了gRPC是什么以及怎么快速启动,那么现在,我们来看看这个玩意具体内部是怎么运作的,这里我们同样以helloworld这个为例子来去谈.首先上期内容在这 ...

  2. Unity中进行网络通信:三:unity客户端和Unity服务端互相发消息

    目录 一.目的 1.想知道:Unity中进行网络通信:unity客户端和Unity服务端互相发消息 二.参考 1.unity3D中使用Socket进行数据通信(三) 三.操作:一:完成:在同一个Uni ...

  3. 附件统一处理starter,含附件客户端和附件服务端

    文章目录 附件统一处理starter,可分别作为附件客户端和附件服务端使用 一 关于项目中附件的概述 二 概要描述 三 附件starter功能划分 3.1 附件服务器,真实的存储附件 3.1.1 为前 ...

  4. http 缓存分为客户端缓存和服务端缓存

    http 缓存分为客户端缓存和服务端缓存 1. 客户端缓存 客户端缓存指的是浏览器缓存, 浏览器缓存是最快的缓存, 因为它直接从本地获取(但有可能需要发送一个请求), 它的优势是可以减少网络流量, 加 ...

  5. 解决android客户端上传图片到服务端时,图片损坏的问题

    解决android客户端上传图片到服务端时,图片损坏的问题 参考文章: (1)解决android客户端上传图片到服务端时,图片损坏的问题 (2)https://www.cnblogs.com/cnbl ...

  6. Linux Socket 两个客户端通信,服务端作为中转

    Socket 两个客户端通信,服务端作为中转 Socket两个客户端通信,服务端作为中转,通过sockket的通信原理,简单的做了一个以c语言写的服务端,与自己制作的Android app 与树莓派为 ...

  7. C# 客户端Client与服务端Server通信

    C# 客户端Client与服务端Server通信 服务端配置 服务端要先启动,等待客户端请求连接 客户端配置 客户端测试**(切记一定要先开启服务端,不然不能保证连接)**

  8. PhotonServer,客户端发送请求给服务端,服务端解析请求,发送回客户端响应,客户端再解析服务端发过来的响应。

    1.(客户端发送给服务端)test中的构造参数并且发送 完整代码如下 test.cs using System; using System.Collections; using System.Coll ...

  9. oracle 客户端无法连接,Oracle客户端无法连接服务端解决方法及步骤

    客户端无法连接服务端数据库,原因有网络,配置,文件访问权限,数据库服务是否已启动 等问题导致,一般排查的步骤如下: 1.检查操作系统级别网络是否通畅 ping 192.168.10.1 2.检查数据库 ...

  10. etcd-03 _ etcdctl:客户端操作 etcd 服务端的工具

    etcd-03 _ etcdctl:客户端操作 etcd 服务端的工具 参考 [拉钩教育 etcd核心原理]

最新文章

  1. 设计模式学习----装饰器模式
  2. Java矩形区域食物链_AcWing 240. 食物链(JAVA)
  3. 一篇文章教会你使用html+css3制作GIF图
  4. C#--序列化与反序列化
  5. selenium 无法启动IE浏览器的解决方法
  6. 典型的同步客户端、服务器端套接字的创建
  7. python编程软件哪个好-来 看看谁最适合学Python编程
  8. 【转】JavaScript生成GUID的算法
  9. 木材材积表快速计算器_原木材积计算器
  10. 汉字拼音首字母检索筛选数据
  11. 【VBA】Str与CStr辨析
  12. java实验三 敏捷开发与XP实践
  13. 还在为英语学习发愁吗?身为程序员的你可能需要这样一份“宝典”(上)...
  14. 在小鸟云新春采购节买到划算的云服务器
  15. pandas后台导出excel_利用pandas将numpy数组导出生成excel
  16. 脿什么意思_襆怎么读_襆组词和拼音
  17. SpringCloud_JZZ_MBY
  18. 安卓电子市场_五款安卓工具神器
  19. 文本分析--NLTK自然语言处理
  20. html在线预览ppt excel,JavaScript实现Word、Excel、PPT在线预览

热门文章

  1. 马鞍山职业计算机考试,2020年职业适应性(技能)测试纲要
  2. PHP密码生成管理源码,php密码生成类(附源码)
  3. spring启动加载流程
  4. 13-Qt6 QMap
  5. 微星笔记本电脑恢复出厂或者一键还原图文流程
  6. top中的res只增不减_tensorflow中张量排序与accuracy计算
  7. 如何取消掉计算机更新图标,XP系统如何关闭右下角中的自动更新图标?
  8. 通讯录新建分组功能php,微信通讯录分组怎么设置
  9. python合并excel文件关键字_使用 Python 合并多个格式一致的 Excel 文件,Excel 表格...
  10. html5抬头,HTML !DOCTYPE 标签