GRPC 入门

GRPC 入门

  • 以前写过socket的protocol buffer,server是c++的 所以上手grpc还是蛮快的,不过 没写过也没接触过的也不要紧 跟着我的步骤走 都是能走通的。我主要是先用java搭个客户端和server 然后跑了ios和android的demo,直接接的java的server

比较详细 权威的官方文档 http://doc.oschina.net/grpc?t=56831

英文好的 来这里 https://grpc.io/docs/ 因为中文资料中很多链接都是不通的,步骤也不太对 所以我是两个一起看的,不看怎么知道中文资料坑多呢?。英文资料比中文资料靠谱多了,如果你按这个所谓的权威中文走,会走很多弯路,内心大骂坑太多,但其实人家英文上都很好的说明解释了,步骤简单明确。

http的双工通信 手机App用起来不错

gRPC 是一个高性能、开源和通用的 RPC 框架,面向移动和 HTTP/2 设计。目前提供 C、Java 和 Go 语言版本,分别是:grpc, grpc-java, grpc-go. 其中 C 版本支持 C, C++, Node.js, Python, Ruby, Objective-C, PHP 和 C# 支持.

gRPC 基于 HTTP/2 标准设计,带来诸如双向流、流控、头部压缩、单 TCP 连接上的多复用请求等特。这些特性使得其在移动设备上表现更好,更省电和节省空间占用。

JAVA http://doc.oschina.net/grpc?t=60134

先跑一遍java的demo试一下 因为跑android和ios之前 也要先搭个服务器,所以先用java跑个客户端和服务器 下边这些命令依次执行 是用来下载demo代码 和编译client和server 还有 运行client和sever的
(https://grpc.io/docs/quickstart/java.html 看了很多资料 这个资料是最靠谱 最容易操作的,那个中文版的 真的太啰嗦了,木有重点)

#这里一定要选分支,不然 默认的master分支 一般用户都会报错的 官方的readme上说 没贡献的开发者是不给用master的
$ git clone -b v1.17.0 https://github.com/grpc/grpc-java
$ cd grpc-java/examples
$ ./gradlew installDist
$ ./build/install/examples/bin/hello-world-server
$ ./build/install/examples/bin/hello-world-client

到这里 就算运行起来了,下面说的是改proto 如果你只是做client 你可以直接跳到android和ios的client的操作步骤上去,server的启动准备算是finish了
改一下服务协议,运行效果看一下 来体会一下通信过程,这个搞懂了原理的话,基本可以上手写个简单的聊天或者广播程序了。
src/main/proto/helloworld.proto 这个是通讯协议,改这个文件

// The greeting service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {}
  // Sends another greeting
  rpc SayHelloAgain (HelloRequest) returns (HelloReply) {}
}

// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings
message HelloReply {
  string message = 1;
}

src/main/java/io/grpc/examples/helloworld/HelloWorldServer.java 这个是服务端代码 改下

private class GreeterImpl extends GreeterGrpc.GreeterImplBase {

  @Override
  public void sayHello(HelloRequest req, StreamObserver responseObserver) {
    HelloReply reply = HelloReply.newBuilder().setMessage("Hello " + req.getName()).build();
    responseObserver.onNext(reply);
    responseObserver.onCompleted();
  }

  @Override
  public void sayHelloAgain(HelloRequest req, StreamObserver responseObserver) {
    HelloReply reply = HelloReply.newBuilder().setMessage("Hello again " + req.getName()).build();
    responseObserver.onNext(reply);
    responseObserver.onCompleted();
  }
}
...

src/main/java/io/grpc/examples/helloworld/HelloWorldClient.java 这个是客户端代码 改下

public void greet(String name) {
  logger.info("Will try to greet " + name + " ...");
  HelloRequest request = HelloRequest.newBuilder().setName(name).build();
  HelloReply response;
  try {
    response = blockingStub.sayHello(request);
  } catch (StatusRuntimeException e) {
    logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus());
    return;
  }
  logger.info("Greeting: " + response.getMessage());
  try {
    response = blockingStub.sayHelloAgain(request);
  } catch (StatusRuntimeException e) {
    logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus());
    return;
  }
  logger.info("Greeting: " + response.getMessage());
}

改好了通信协议,server和client,就可以编译运行了

$ ./gradlew installDist
$ ./build/install/examples/bin/hello-world-server
$ ./build/install/examples/bin/hello-world-client

Android https://grpc.io/docs/quickstart/android.html

你如果把java server和client运行完了 会发现文件夹里有android,对滴,还是这个项目,到android文件夹里去编译运行android就好了

$ cd android/helloworld
$ ../../gradlew installDebug

改个代码看一下(server和proto的代码改动请参照上文,这里只说一下android代码的改动)
app/src/main/java/io/grpc/helloworldexample/HelloworldActivity.java

 try {
        HelloRequest message = HelloRequest.newBuilder().setName(mMessage).build();
        HelloReply reply = stub.sayHello(message);
        reply = stub.sayHelloAgain(message);
    } catch (Exception e) {
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        e.printStackTrace(pw);
        pw.flush();
        return "Failed... : " + System.lineSeparator() + sw;
    }

Objective-C https://grpc.io/docs/quickstart/objective-c.html

利用之前的java服务器来测试oc的客户端 也可以搭个C++的服务器 都一样的 没影响 protocol buffer是字节流,平台无关的
先拉demo代码 跑起来 跟前面的server通个信(这个demo里对应的server是c++的 可以用这个server 也可以用前面run起来的server)

$ git clone --recursive -b v1.17.1 https://github.com/grpc/grpc.git
$ cd grpc
$ make
$ [sudo] make install
$ brew tap grpc/grpc
$ brew install protobuf
$ cd examples/objective-c/helloworld
$ pod install
$ open HelloWorld.xcworkspace

刚才改过java的protocol和server 现在改一下ios代码看下效果 examples/objective-c/helloworld/main.m

int main(int argc, char * argv[]) {
  @autoreleasepool {
    [GRPCCall useInsecureConnectionsForHost:kHostAddress];
    [GRPCCall setUserAgentPrefix:@"HelloWorld/1.0" forHost:kHostAddress];

    HLWGreeter *client = [[HLWGreeter alloc] initWithHost:kHostAddress];

    HLWHelloRequest *request = [HLWHelloRequest message];
    request.name = @"Objective-C";

    [client sayHelloWithRequest:request handler:^(HLWHelloReply *response, NSError *error) {
      NSLog(@"%@", response.message);
    }];
    [client sayHelloAgainWithRequest:request handler:^(HLWHelloReply *response, NSError *error) {
      NSLog(@"%@", response.message);
    }];

    return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
  }
}

如果不用之前的java的server 也可以用这个demo里的c++server

$ cd examples/cpp/helloworld
$ make
$ ./greeter_server &

那改ios代码的时候 就要记得改对应的proto和c++server代码
examples/protos/helloworld.proto

// The greeting service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {}
  // Sends another greeting
  rpc SayHelloAgain (HelloRequest) returns (HelloReply) {}
}

// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings
message HelloReply {
  string message = 1;
}

examples/cpp/helloworld/greeter_server.cc

class GreeterServiceImpl final : public Greeter::Service {
  Status SayHello(ServerContext* context, const HelloRequest* request,
                  HelloReply* reply) override {
    std::string prefix("Hello ");
    reply->set_message(prefix + request->name());
    return Status::OK;
  }
  Status SayHelloAgain(ServerContext* context, const HelloRequest* request,
                  HelloReply* reply) override {
    std::string prefix("Hello again ");
    reply->set_message(prefix + request->name());
    return Status::OK;
  }
};

改了server 就编译运行一下c++的server

$ pkill greeter_server
$ make
$ ./greeter_server &

Error Error Error !!!

执行命令过程中 肯定会遇到很多failed 这里整理了一些 我遇到的

  • $ ./gradlew installDist 执行这个 编译的时候报错 Could not find io.grpc:grpc-protobuf:1.18.0-SNAPSHOT.
    解决办法:https://github.com/grpc/grpc-java/issues/5083
    意思就是说,你不能拉master分支 要去拉release分支,如果已经clone了 就去切分支就好了(但不能切.x分支 因为也会找不到对应的.x的maven库,要去切定版)

  • $ ./gradlew installDist 执行这个 编译的时候报错 Could not resolve com.jcraft:jsch:0.1.54.
    解决办法:检查一下你的npm的Registry源,切到淘宝上去就好了

  • $ ./gradlew installDist 执行这个 编译的时候报错 Execution failed for task ‘:grpc-compiler:compileJava_pluginExecutableJava_pluginCpp’.
    解决办法:c++的编译问题,在pom文件中加一些属性和依赖


   com.google.guava
   guava
   23.6-jre
 

   org.apache.httpcomponents
   httpcore
   4.4.8




   
       profile1
       
         com.SomeClass
       
   
   
       profile2
       
         com.SomeOtherClass
       
   





   org.springframework.boot
   spring-boot-maven-plugin
   1.5.2.RELEASE
   
     
       
         repackage
       
       
         ${spring.boot.mainclass}
       
     
   
   ...




  • $ …/…/gradlew installDebug 执行这个 编译的时候报错 Could not find any version that matches io.grpc:grpc-core:[1.17.1].
    解决办法:真的对官方的demo无语了,

https://111qqz.com/2018/10/java-grpc-踩坑记录/
也可以看看这个坑友的 他的坑和我遇到的坑不一样

你可能感兴趣的:(Android,iOS,RN,JAVA)