下载demo请点击这里
以下是通过idea创建项目,熟悉的可以直接看下一步
syntax = "proto3";
service TestService{
// 第一种
rpc add(TRequest) returns (TReply){}
// 第二种
rpc min(TRequest) returns(stream TReply){}
// 第三种
rpc max(stream TRequest) returns(stream TReply){}
// 第四种
rpc talk(stream Msg) returns(stream Msg){}
}
public class TestServer extends TestServiceGrpc.TestServiceImplBase {
private StreamObserver<Msg> responseObserver;
@Override
public void add(TRequest request, StreamObserver<TReply> responseObserver) {
int res = myAdd(request.getA(), request.getB());
responseObserver.onNext(TReply.newBuilder().setRes(res).build());
responseObserver.onCompleted();
}
@Override
public void min(TRequest request, StreamObserver<TReply> responseObserver) {
int myMin = myMin(request.getA(), request.getB());
responseObserver.onNext(TReply.newBuilder().setRes(myMin).build());
responseObserver.onCompleted();
}
@Override
public StreamObserver<TRequest> max(StreamObserver<TReply> responseObserver) {
return new StreamObserver<TRequest>() {
@Override
public void onNext(TRequest tRequest) {
int myMax = myMax(tRequest.getA(), tRequest.getB());
responseObserver.onNext(TReply.newBuilder().setRes(myMax).build());
}
@Override
public void onError(Throwable throwable) {
responseObserver.onError(throwable);
}
@Override
public void onCompleted() {
responseObserver.onCompleted();
}
};
}
@Override
public StreamObserver<Msg> talk(StreamObserver<Msg> responseObserver) {
this.responseObserver = responseObserver;
return new StreamObserver<Msg>() {
@Override
public void onNext(Msg msg) {
System.out.println("进入talk:" + msg.getMsg());
// responseObserver.onNext(msg);
}
@Override
public void onError(Throwable throwable) {
responseObserver.onError(throwable);
}
@Override
public void onCompleted() {
System.out.println("onCompleted");
responseObserver.onCompleted();
}
};
}
public StreamObserver<Msg> getResponseSo() {
return responseObserver;
}
}
public class TestClient {
TestServiceGrpc.TestServiceBlockingStub blockingStub;
TestServiceGrpc.TestServiceStub stub;
ManagedChannel channel;
int port = 10086;
boolean isD = false;
public static void main(String[] args) {
TestClient client = new TestClient();
Scanner scanner = new Scanner(System.in);
// max
StreamObserver<TRequest> maxRequest = client.stub.max(new MyStreamObserver<TReply>("max", tReply -> System.out.println("max:结果为:" + tReply.getRes())));
StreamObserver<Msg> talkRequest = client.stub.talk(new MyStreamObserver<Msg>("talk", msg -> System.out.println("服务端:" + msg.getMsg())));
while (true) {
if (!client.isD)
System.out.println("请先确定方式:\n\r a:add b:min c:max d:talk q:quit");
String type = scanner.nextLine();
if (type.equals("q")) {
if (client.isD) {
client.isD = false;
} else {
maxRequest.onCompleted();
talkRequest.onCompleted();
client.channel.shutdown();
break;
}
}
if (client.isD) {
talkRequest.onNext(Msg.newBuilder().setMsg(type).build());
} else
switch (type) {
case "a":
// add
System.out.println("请输入两个数 用空格分开");
String[] s = scanner.nextLine().split(" ");
if (s.length >= 2) {
int i1 = Integer.parseInt(s[0]);
int i2 = Integer.parseInt(s[1]);
try {
TReply reply = client.blockingStub.add(TRequest.newBuilder().setA(i1).setB(i2).build());
System.out.println("结果为:" + reply.getRes());
} catch (Exception e) {
System.out.println("发生错误:" + e.getMessage());
}
} else {
System.out.println("输入错误!");
}
break;
case "b":
// min
System.out.println("请输入两个数 用空格分开");
s = scanner.nextLine().split(" ");
if (s.length >= 2) {
int i1 = Integer.parseInt(s[0]);
int i2 = Integer.parseInt(s[1]);
try {
Iterator<TReply> it = client.blockingStub.min(TRequest.newBuilder().setA(i1).setB(i2).build());
TReply reply;
while (it.hasNext()) {
reply = it.next();
System.out.println("结果为:" + reply.getRes());
}
} catch (Exception e) {
System.out.println("发生错误:" + e.getMessage());
}
} else {
System.out.println("输入错误!");
}
break;
case "c":
// min
System.out.println("请输入两个数 用空格分开");
s = scanner.nextLine().trim().split(" ");
if (s.length >= 2) {
int i1 = Integer.parseInt(s[0]);
int i2 = Integer.parseInt(s[1]);
try {
maxRequest.onNext(TRequest.newBuilder().setA(i1).setB(i2).build());
} catch (Exception e) {
System.out.println("发生错误:" + e.getMessage());
}
} else {
System.out.println("输入错误!");
}
break;
case "d":
client.isD = true;
System.out.println("请输入内容");
break;
}
}
}
public TestClient() {
channel = ManagedChannelBuilder
.forAddress("127.0.0.1", port)
.usePlaintext()
.build();
stub = TestServiceGrpc.newStub(channel);
blockingStub = TestServiceGrpc.newBlockingStub(channel);
}
}
写到这里,就可以在电脑端进行测试
buildscript {
dependencies {
....
classpath "com.google.protobuf:protobuf-gradle-plugin:0.8.17"
}
}
plugins {
...
id 'com.google.protobuf'
}
protobuf {
protoc { artifact = 'com.google.protobuf:protoc:3.17.2' }
plugins {
javalite { artifact = "com.google.protobuf:protoc-gen-javalite:3.0.0" }
grpc {
artifact = 'io.grpc:protoc-gen-grpc-java:1.42.1' // CURRENT_GRPC_VERSION
}
}
generateProtoTasks {
all().each { task ->
task.builtins {
java { option 'lite' }
}
task.plugins {
grpc { // Options added to --grpc_out
option 'lite'
}
}
}
}
//配置proto生成java代码的目录 (可选)
generatedFilesBaseDir = "$projectDir/src/generated"
}
dependencies {
...
implementation 'io.grpc:grpc-okhttp:1.42.1' // CURRENT_GRPC_VERSION
implementation 'io.grpc:grpc-protobuf-lite:1.42.1' // CURRENT_GRPC_VERSION
implementation 'io.grpc:grpc-stub:1.42.1' // CURRENT_GRPC_VERSION
implementation 'org.apache.tomcat:annotations-api:6.0.53'
}
引入相关proto文件并重新rebuild项目来生成相关的java代码
与服务端建立通讯
private fun init() {
// 在这里根据IP地址和端口号创建管道
channel = ManagedChannelBuilder.forAddress(address, port).usePlaintext().build()
// 然后根据管道创建 stub
// 这俩的区别是 blockingStub是阻塞式的,stub是异步的,
// 通过调用就可以看出来它们的区别
stub = TestServiceGrpc.newStub(channel)
blockingStub = TestServiceGrpc.newBlockingStub(channel)
}
// 直接通过blockingStub调用方法,它是阻塞式的,直接是等待服务端返回结果
// reply 就是服务端返回的数据
val reply = blockingStub?.add(TRequest.newBuilder().setA(str1.toInt()).setB(str2.toInt()).build())
bind.tvResult.text = reply?.res.toString()
// 首先是设置服务端的数据回调
// 下面就是拿着这个request来进行访问
// stub就是异步的
talkRequest = stub?.talk(MyStreamObserver("talk", object : OnResult<Msg> {
@SuppressLint("NotifyDataSetChanged")
override fun onNext(v: Msg) {
// 这里就是服务端返回的数据
}
}))
// 下面就是直接通过onNext方法就可以把数据传给服务端,
// 服务端返回的数据就会通过上面的回调函数传过来
talkRequest?.onNext(Msg.newBuilder().setMsg(str).build())
好了,这里就列举了add和talk两个实现方式不同的方法,其他的都跟这俩类似,就不重复写了。