12

Is it possible to only stream to certain clients from a gRPC server?

I believe what I'm looking for is something like Pusher, where you have a channel for a client and you can publish messages that can be seen only by a client that has access to that channel.

What I'm struggling with is understanding what are the steps we need to take to do something like this.

Thinking about web-sockets I believe we can store each client connection, then we can find that connection and send messages. How can we do a similar thing with gRPC?

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
user2502761
  • 563
  • 1
  • 6
  • 18

1 Answers1

7

As per as i understood the question. You want to send the the message to the particular client in gRPC. This is very much possible using Server side streaming or Bi-directional streaming in gRPC.

For example:

Define a server side streaming or bidi streaming api

rpc ListFeatures(Rectangle) returns (stream Feature) {}

On Server side:

func ListFeatures(rect *pb.Rectangle, stream pb.RouteGuide_ListFeaturesServer) error {
  // Save this stream instance in the server on a map or other suitable data structure
  // so that you can query for this stream instance later
  // This will act same like your websocket session
}

When you want to send something to a specific client then get the stream instance and do

err := stream.Send(feature); // Any times as required

On the client, it will be waiting for messages like this

stream, err := client.ListFeatures(ctx, rect)

for {
    feature, err := stream.Recv()
    ...
    // handle message here
}

Same thing can be done for bidi streaming rpc also. I hope this answers your question

Shettyh
  • 1,188
  • 14
  • 27
  • Can you please guide how to keep the connection in client open so that further responses from streaming server can be received by client? – Prashant Shubham Aug 31 '18 at 19:02
  • `feature, err := stream.Recv()` this is basically a blocking call, it waits until it receives the message from server. And this wait is inside a infinite `for loop`, so it wait for server to send messages indefinitely. Only thing is this code should be inside `go routine` so that it will receive messages from server asynchronously while client can do other things in main thread. – Shettyh Sep 01 '18 at 01:11
  • I wanted the same to do in C++, but when I put the code in while loop it breaks. Can you please guide me? – Prashant Shubham Sep 01 '18 at 05:26
  • Take a look at this https://github.com/grpc/grpc/blob/master/examples/cpp/route_guide/route_guide_client.cc#L86 – Shettyh Sep 01 '18 at 08:39
  • Thanks figured it out. Just one more help, can you guide me how to stop client from timeout ClientContext::set_deadline is not working . – Prashant Shubham Sep 01 '18 at 08:40
  • Try setting deadline like this https://github.com/grpc/grpc/blob/master/test/cpp/end2end/end2end_test.cc#L1306 – Shettyh Sep 01 '18 at 08:51
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/179232/discussion-between-prashant-shubham-and-shettyh). – Prashant Shubham Sep 01 '18 at 08:57