Java
getStuNo.proto
syntax = "proto3";
option java_multiple_files = true;
option java_package = "io.grpc.examples.getstuno";
option java_outer_classname = "GetStuNoProto";
option objc_class_prefix = "GSN";
package getstuno;
service GetStuNoService {
rpc getMsg (StuNoRequest) returns (StuNoResponse){}
}
message StuNoRequest {
string name = 1;
}
message StuNoResponse {
string number = 1;
}
protocol buffers 是一种语言无关、平台无关、可扩展的序列化结构数据的方法,它可用于(数据)通信协议、数据存储。这里使用proto文件用于生成gRPC所需要的框架。生成方式参照https://blog.csdn.net/qq_29319189/article/details/93539198
GetStuNoServer.java
package getstuno;
import io.grpc.Server;
import io.grpc.ServerBuilder;
import io.grpc.examples.getstuno.GetStuNoServiceGrpc;
import io.grpc.examples.getstuno.StuNoResponse;
import io.grpc.examples.getstuno.StuNoRequest;
import io.grpc.stub.StreamObserver;
import java.io.IOException;
import java.util.logging.Logger;
/**
* Server that manages startup/shutdown of a {@code Greeter} server.
*/
public class GetStuNoServer {
private static final Logger logger = Logger.getLogger(GetStuNoServer.class.getName());
private Server server;
private void start() throws IOException {
/* The port on which the server should run */
int port = 50051;
server = ServerBuilder.forPort(port)
.addService(new GetStuNoServiceImpl())
.build()
.start();
logger.info("Server started, listening on " + port);
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
// Use stderr here since the logger may have been reset by its JVM shutdown hook.
System.err.println("*** shutting down gRPC server since JVM is shutting down");
GetStuNoServer.this.stop();
System.err.println("*** server shut down");
}
});
}
private void stop() {
if (server != null) {
server.shutdown();
}
}
/**
* Await termination on the main thread since the grpc library uses daemon threads.
*/
private void blockUntilShutdown() throws InterruptedException {
if (server != null) {
server.awaitTermination();
}
}
/**
* Main launches the server from the command line.
*/
public static void main(String[] args) throws IOException, InterruptedException {
final GetStuNoServer server = new GetStuNoServer();
server.start();
server.blockUntilShutdown();
}
static class GetStuNoServiceImpl extends GetStuNoServiceGrpc.GetStuNoServiceImplBase {
@Override
public void getMsg(StuNoRequest req, StreamObserver<StuNoResponse> responseObserver) {
String number = "0000";
logger.info("Received name: " + req.getName());
if (req.getName().equals("爱丽丝")) {
number = "1234";
}
StuNoResponse reply = StuNoResponse.newBuilder().setNumber(number).build();
responseObserver.onNext(reply);
responseObserver.onCompleted();
}
}
}
Server端重点实现提供的服务
GetStuNoClient.java
package getstuno;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.StatusRuntimeException;
import io.grpc.examples.getstuno.GetStuNoServiceGrpc;
import io.grpc.examples.getstuno.StuNoResponse;
import io.grpc.examples.getstuno.StuNoRequest;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* A simple client that requests a greeting from the {@link GetStuNoServer}.
*/
public class GetStuNoClient {
private static final Logger logger = Logger.getLogger(GetStuNoClient.class.getName());
private final ManagedChannel channel;
private final GetStuNoServiceGrpc.GetStuNoServiceBlockingStub blockingStub;
/** Construct client connecting to GetStuNo server at {@code host:port}. */
public GetStuNoClient(String host, int port) {
this(ManagedChannelBuilder.forAddress(host, port)
// Channels are secure by default (via SSL/TLS). For the example we disable TLS to avoid
// needing certificates.
.usePlaintext()
.build());
}
/** Construct client for accessing HelloWorld server using the existing channel. */
GetStuNoClient(ManagedChannel channel) {
this.channel = channel;
blockingStub = GetStuNoServiceGrpc.newBlockingStub(channel);
}
public void shutdown() throws InterruptedException {
channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
}
/** Say hello to server. */
public void greet(String name) {
StuNoRequest request = StuNoRequest.newBuilder().setName(name).build();
StuNoResponse response;
try {
response = blockingStub.getMsg(request);
} catch (StatusRuntimeException e) {
logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus());
return;
}
logger.info("Client received: " + response.getNumber());
}
/**
* Greet server. If provided, the first element of {@code args} is the name to use in the
* greeting.
*/
public static void main(String[] args) throws Exception {
GetStuNoClient client = new GetStuNoClient("localhost", 50051);
try {
/* Access a service running on the local machine on port 50051 */
String user = "爱丽丝";
if (args.length > 0) {
user = args[0]; /* Use the arg as the name to greet if provided */
}
client.greet(user);
} finally {
client.shutdown();
}
}
}
Client端向Server端请求服务
Python
getStuNo.proto
syntax = "proto3";
package getstuno;
service GetStuNoService {
rpc getMsg (StuNoRequest) returns (StuNoResponse){}
}
message StuNoRequest {
string name = 1;
}
message StuNoResponse {
string number = 1;
}
Python与Java的proto文件基本相同,重点在于package必须相同,否则当提供名称、类型相同的service和message时仍然无法沟通。python利用proto生成grpc框架的方法参照:
https://www.cnblogs.com/zongfa/p/12218341.html
server.py
import grpc
import getStuNo_pb2
import getStuNo_pb2_grpc
from concurrent import futures
import time
_ONE_DAY_IN_SECONDS = 60 * 60 * 24
class GetStuNoServicer(getStuNo_pb2_grpc.GetStuNoServiceServicer):
def getMsg(self, request, context):
print("Received name: %s" % request.name)
if request.name == '爱丽丝':
number = '1234'
else:
number = '0000'
return getStuNo_pb2.StuNoResponse(number=number)
def serve():
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
getStuNo_pb2_grpc.add_GetStuNoServiceServicer_to_server(GetStuNoServicer(), server)
server.add_insecure_port('[::]:50051')
server.start()
try:
while True:
time.sleep(_ONE_DAY_IN_SECONDS)
except KeyboardInterrupt:
server.stop(0)
if __name__ == '__main__':
serve()
client.py
import grpc
import getStuNo_pb2
import getStuNo_pb2_grpc
def run():
# NOTE(gRPC Python Team): .close() is possible on a channel and should be
# used in circumstances in which the with statement does not fit the needs
# of the code.
with grpc.insecure_channel('localhost:50051') as channel:
stub = getStuNo_pb2_grpc.GetStuNoServiceStub(channel)
response = stub.getMsg(getStuNo_pb2.StuNoRequest(name='爱丽丝'))
print("Client received: " + response.number)
if __name__ == '__main__':
run()
python端的代码较为精简。
此时,保证了java和python端的gRPC提供的gRPC服务名,服务传输的变量名、类型,服务使用的端口相同。先启动java或python任意一个server端,再启动java或python任意一个client端,都可以正确提供gRPC服务。











