16
votes

From the introduction on gRPC:

In gRPC a client application can directly call methods on a server application on a different machine as if it was a local object, making it easier for you to create distributed applications and services. As in many RPC systems, gRPC is based around the idea of defining a service, specifying the methods that can be called remotely with their parameters and return types. On the server side, the server implements this interface and runs a gRPC server to handle client calls. On the client side, the client has a stub that provides exactly the same methods as the server.

The above paragraph talks about a client and a server, with the former being the one who is invoking methods to the other. What am I wondering is: can the server-end of the connection invoke methods that have been registered on the client?

3
However if you are a bit crazy you can just encapsulate all calls/responses in stream of envelope message ;-) Maybe it's not the most beautiful solution but it works.Paweł Szczur

3 Answers

18
votes

No, a server cannot invoke calls on the client. gRPC works with HTTP, and HTTP has not had such semantics in the past.

There has been discussion as to various ways to achieve such a feature, but I'm unaware of any work having started or general agreement on a design. gRPC does support bidirectional streaming, which may get you some of what you need. With bidirectional streaming the client can respond to messages from server, but the client still calls the server and only one type of message can be sent for that call.

4
votes

What you can do is start a HTTP server in both processes and use clients at each end to initiate communication. There's a bit of boilerplate involved and you have to design a simple handshaking protocol (one end registers with the other, advertising its listen address) but it's not too much work.

4
votes

The protocol does not implement it, but you may pretend this situation.

Define a server method that returns a stream of a ServerRequest message:


import "google/protobuf/any.proto";

service FullDuplex {
    rpc WaitRequests (google.protobuf.Any) returns (stream ServerRequest);
}

message ServerRequest {
    float someValue = 1;

    float anotherAnother = 1;
}

ServerRequest may be an Oneof, so your may receive different types of server requests.

If you need that your client sends back a response for each request, you may create a stream from your client to the server, but you will need to implement a logic in your server side that triggers a timeout waiting for that response.

service FullDuplex {
    rpc WaitRequests (stream ClientResponse) returns (stream ServerRequest);
}