gRPC c++ check client disconnection

1,642 views
Skip to first unread message

Filip Mrázek

unread,
Apr 2, 2021, 6:43:21 AM4/2/21
to grpc.io
Hi,
I would like to write gRPC server in C++, which is able to detect if client disconnected from the channel (client crashed or closed app). I need this, because server manages a physical robot and only one client can controll the robot at the same time (other clients can check only robot's properties such as position and so on).
I've got rpc connect(ConnectionInfo) returns(Token) where ConnectionInfo contains information wheater client wants to control robot (wants to be master) or not and if it's possible, server returns access token. After the master client disconnects, I want to remove token from server to able other clients connect as master.
The only solution I found out is to have rpc disconnect() returns(Empty), but I doesn't cover case when client crash or just forget to call disconnect and robot is blocked.
Is it possible with c++ gRPC, or what whould you recommend as the best solution fot this problem? 
Thank you very much.

Filip.

PS: I found several discussions, but none of them is helpful.

Sunandan Nandi

unread,
Apr 6, 2021, 3:02:31 PM4/6/21
to grpc.io
Hi Filip,
I believe I can understand your problem.

As you have mentioned your client is master or controller for Robot, right?
In that case how are you sending the control instruction to the robot, is there any stream then you can easily detect the client disconnection.
If you are reading at server end when the client dies the read will not return true, so you can understand from there.

Otherwise you have to introduce some new API to notify client disconnection and keep that call in catch() block somehow. That may help.

Regards,
SN

Filip Mrázek

unread,
Apr 6, 2021, 5:24:13 PM4/6/21
to grpc.io
Hi,
thak you for your reply. Client controls robot (after calling connect with master request) via several unary rpc calls (move, setTool, etc.). I was thinking about something like this: rpc (stream Control) returns (stream ControlResponse), but it's hard to create clean elegant Control message to contain everything needed. It would be nice to be able to send multiple message types. (and I think it's possible only with oneof nowadays, which I don't like, beacause every new command means to edit proto on two locations (new message type and adding message to oneof).
Anyway, am I able to detect client cannot send request with stream? (he disconnected) How? Is there any example, please?
Thanks.

Regards,

Filip. 
Dne úterý 6. dubna 2021 v 21:02:31 UTC+2 uživatel sunanda...@gmail.com napsal:

tobias.krueger

unread,
Apr 7, 2021, 2:56:56 AM4/7/21
to grpc.io
Hi Filip,

from my experience streams are difficult to handle when it comes to a (un)reliable channels.
Especially if you have to deal with crashing or ungraceful disconnecting clients.
The client has no control if a sent packet has reached the server or not not. The same applies to the back channel: The server does not know if the client crashed or is just idle.

IMHO it is also not feasible to invent your own handshake on top of an unreliable streamed channel - this is something that a communication framework can do better.
I would stick with unary rpcs.

Best regards

Filip Mrázek

unread,
Apr 8, 2021, 4:51:42 AM4/8/21
to grpc.io
Thank you Tobias for your answer. If I understand your answer, you suggest to stick with unary rpcs and use already done communication framework (on top of grpc?) . Do you know any which would be easy to learn and sufficient 
for this case? Thank you

Regards,

Filip
Dne středa 7. dubna 2021 v 8:56:56 UTC+2 uživatel tobias.krueger napsal:

tobias.krueger

unread,
Apr 12, 2021, 5:36:36 AM4/12/21
to grpc.io
> you suggest to stick with unary rpcs

I would recommend to test all stability - / interrupt - / reconnect - scenarios before switching to a stream based communication completely.
In my case I found much easier to handle all these edge-cases with unary calls. 

>  framework (on top of grpc?). Do you know any 
No - I do not know any framework here. 

For me the unary calls are comparable to TCP - you will get an acknowledge if the message was received correctly.
The GRPC stream is more like an UDP communication - if you want to be sure, that a  message   is transmitted correctly you have to invent you own handshake.

Sunandan Nandi

unread,
Apr 13, 2021, 3:55:02 AM4/13/21
to Filip Mrázek, grpc.io
Hi Filip,

Sorry for the delayed response,
server sample code works like below

grpc::Status StreamMethod(servercontext ..)
{

...
while(interface->Read()){


}//if your client is killed then, your server Read will come out of while 
}

So tested this in VS.If I close my client then server-side will come out of this Reading () loop.

Regards,
SN


--
You received this message because you are subscribed to a topic in the Google Groups "grpc.io" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/grpc-io/KRhWNAoPUO8/unsubscribe.
To unsubscribe from this group and all its topics, send an email to grpc-io+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/grpc-io/e906121c-5710-48ea-a40f-ff313fe70779n%40googlegroups.com.

tobias.krueger

unread,
Apr 13, 2021, 4:06:23 AM4/13/21
to grpc.io
Hi Sunandan,
have you tried your sample some edge cases, where for example
- you switch of a WLAN connection between client/server
- plug-out the LAN cable before or after the switch
- close a VPN connection that might be used.
If you running the client and server on the same machine or you have a 1:1 cable in-between it is much more reliable.

In my experience we have seen several cases where while loop is not be left reliable in a time, that is below my patience .
We had to fiddle with the timeout parameters (GRPC_ARG_KEEPALIVE_TIME_MS etc.) to get an acceptable behavior after such interrupts .

Best regards
Tobias

Filip Mrázek

unread,
Apr 15, 2021, 8:36:59 AM4/15/21
to grpc.io

Hi Sunandan,
thank you for your answer. I tried your solution and it works (however I didn't try edge cases which tobias mentioned). 
Unfortunately I struggle with client in Python. To check everything work on server side I used BloomRPC where I can open stream, send messages over bidirectional stream, keep stream opened, send unary rpcs, send messages over stream and then close the stream. I followed the example provided by grpc and my client code looks like this:
def msgs():
    messages = [
        pb.Command(name="first"),
        pb.Command(name="second"),
        pb.Command(name="third")
    ]
    for msg in messages:
    yield msg
    time.sleep(3)

with grpc.insecure_channel("0.0.0.0:50000") as channel:
    robot = Robot_pb2_grpc.RobotStub(channel)

    for response in robot.control(msgs()):
        print(response)

and I can't figure out how to send unary rpcs while the stream is still open. 

(My aim is to create bidirectional stream for controlling robot (and protect that only one client can open stream at the same time) and keep unary rpcs for getting robot's properties such as position, current tool used and so on)
Dne úterý 13. dubna 2021 v 10:06:23 UTC+2 uživatel tobias.krueger napsal:

Sunandan Nandi

unread,
Apr 18, 2021, 12:44:56 AM4/18/21
to Filip Mrázek, grpc.io
Hi Filip,

In the client-side code if you want to perform two or multiple rpc then you have to do that from the worker threads.

Thank you Tobias for suggesting multiple edge cases.
Regards,
Sunandan

Reply all
Reply to author
Forward
0 new messages