In most RPC systems, the roles of client and server are very asymmetric. All the server does is listen for requests from the client and respond to them:
Yes, it's at any time, because there's actually two clients, and the code on the server could look like this:
1 2 3 4 5 6
void ensure_snafucated(){
if (clientA.has_become_snafucated())
clientB.become_snafucated();
elseif (clientB.wants_to_xyzzyfy())
clientA.xyzzyfy();
}
and while clientB is responding to wants_to_xyzzyfy(), which could take several minutes, clientA could asynchronously ask the server for some other piece of information. I can't predict at all the order of operations.
For the connection establishment one side needs to be the "server" (listening) and the other side needs to be the "client" (connecting). I think there is no way around that. But once the connection has been established, both sides can send/write and receive/read whenever they want, and in any possible interleaved way.
So, there is really no reason why the server shouldn't be able to send a "request" message to any of its connected clients at any time. Of course, it then will be up to the client to answer with a "response" message to the server in a timely manner. If the client does not answer (quickly), the server can not "enforce" it.
Yes, that's what I'm doing, but I would prefer if someone else had already solved the protocol so I don't have to waste my time handling network issues and can concentrate on solving my actual problem.
I am not sure there is a major package that does this by design.
There are all kinds of round-peg-square-hole how-tos with gRPC, and people seem satisfied with the result, but this is way past anything I can tell you beyond doing your own google of "grpc and bidirectional" or the like.
If you don't mind running multiple connections, you can make each box both the server and a client, maybe, with any package.