RPC stands for "Remote Procedure Call", and in YARP is used to refer to communication that consists of a message and a reply to that message.
Historically, YARP has stressed streaming communication (without replies) because in our experience it leads to more robust and scalable control logic. However, RPC definitely has its place, and this tutorial describes how to do it in YARP.
The basic mechanism for getting replies with YARP is described in the getting replies section of the Port Power tutorial. The RPC ports are a thin wrapper around regular ports, for the purpose of restricting flexibility rather than increasing it.
If you intend to use ports for RPC alone, you can use the yarp::os::RpcClient and yarp::os::RpcServer classes. These are just like the regular yarp::os::Port class, except that streaming operation is prohibited. By using these classes, YARP can check for accidental misusage of the ports, and give more helpful error messages.
Here is an example server:
And here is a client to go with it:
The server and client communicate with yarp::os::Bottle objects here, but as usual anything that implements yarp::os::Portable can be used.
Normal streaming communication in YARP is very easy to monitor, just connect another port to the sender. For RPC communication, we have to be a bit more careful.
Suppose the server and client above are running (the source code is in example/os/rpc_server/rpc_server.cpp and example/os/rpc_client/rpc_client.cpp), in two separate terminals, as follows:
./rpc_server /server ./rpc_client /client /server
Here we have named the server port /server
and the client port /client
. Every second or so, the client sends a message to the server with a count in it, and the server replies with "you said" followed by that message.
How can we monitor this traffic remotely? YARP supports a special kind of logging connection called log.in
which can report all the inputs a port is receiving (along with the corresponding replies). We make a connection from the server (not the client) to a logging port, set the connection to log.in
mode, and we are done.
The syntax for doing so is either:
yarp read /read tcp+log.in://server
Or equivalently:
yarp read /read yarp connect /server /read tcp+log.in
The protocol in this case is specified to be tcp (which is the default), but with an added +log.in
decoration. This is a "carrier modifier" that tells YARP that the connection has a special purpose, in this case to log traffic that arrives at the /server
port. Without that modifier, this connection would be forbidden if the RPC server is already connected to a client, and even if it were allowed it would misbehave.
The output shown by the "yarp read" command will be something like this:
[rpc] (COUNT 29) (you said COUNT 29) [rpc] (COUNT 30) (you said COUNT 30) [rpc] (COUNT 31) (you said COUNT 31) [rpc] (COUNT 32) (you said COUNT 32) [rpc] (COUNT 33) (you said COUNT 33) [rpc] (COUNT 34) (you said COUNT 34) [rpc] (COUNT 35) (you said COUNT 35) [rpc] (COUNT 36) (you said COUNT 36)
The first element is a tag for RPC traffic. The second element is a nested list describing the input received by the port. The third element is a nested list describing the corresponding output produced by the port.
Note that we log from the server side, because we are logging inputs. At this time YARP does not have a log.out
mode for logging outputs with their replies.
The logging connection will pass along any envelope or timestamp associated with the input, and will lack an envelope if the input lacks an envelope.