This section explains how to configure a Request-Reply communication in Fast DDS between two applications. A Client application will send a Request to the Server application and this one, after processing the request, will send a Reply to the Client application.
.. uml:: :align: center node "Client application" as client { } node "Server application" as server { } client --> server : Request server --> client : Reply
This kind of communication involves in the DDS paradigm the usage of two Topics: one for sending requests (Request Topic) and the other one for sending replies (Reply Topic). For managing these Topics four DDS entities are involved: a DataReader and a DataWriter for each Topic. The DDS communication schema will be:
.. uml:: :align: center node "Server application" { cloud "Processing" as Processing [Request DataReader] -right-> Processing Processing -right-> [Reply DataWriter] } node "Client application" { [Reply DataReader] [Request DataWriter] } [Request DataWriter] -down-> [Request DataReader] : Request Topic [Reply DataWriter] --> [Reply DataReader] : Reply Topic
The key for making Request-Reply work is relating the Request with the Reply in the client's side. Fast DDS API provides |SampleIdentity-api| to achieve this.
A full example can be found in Fast DDS repository.
For Request-Reply communication perform the following steps:
Define two structures in an IDL file. One structure will be used as Request Topic's data type and the other one as Reply Topic's data type.
enum OperationType { ADDITION, SUBSTRACTION, MULTIPLICATION, DIVISION }; struct RequestType { OperationType operation; long x; long y; }; struct ReplyType { long long z; };
In the client application, create a DataWriter for the request and a DataReader for the reply.
.. literalinclude:: ../../../../code/DDSCodeTester.cpp :language: c++ :dedent: 4 :start-after: //REQUEST_REPLY_EXAMPLE_CLIENT_CREATE_ENTITIES :end-before: //!
In the server application, create a DataWriter for the reply and a DataReader for the request.
.. literalinclude:: ../../../../code/DDSCodeTester.cpp :language: c++ :dedent: 4 :start-after: //REQUEST_REPLY_EXAMPLE_SERVER_CREATE_ENTITIES :end-before: //!
For sending the request, the client application should retrieve and store the internal identifier assigned to the published sample. Therefore the sample should be published using the overloaded |DataWriter::write-api| function which second argument is a reference to a |WriteParams-api| object. The assigned identifier will be stored in the |WriteParams-api|'s attribute |WriteParams-sample_identity-api|.
.. literalinclude:: ../../../../code/DDSCodeTester.cpp :language: c++ :dedent: 4 :start-after: //REQUEST_REPLY_EXAMPLE_CLIENT_RETRIEVE_ID :end-before: //!
When the server application receives the request (for example through |DataReaderListener::on_data_available-api|), it has to retrieve the request's identifier using |SampleInfo::sample_identity-api|.
.. literalinclude:: ../../../../code/DDSCodeTester.cpp :language: c++ :dedent: 4 :start-after: //REQUEST_REPLY_EXAMPLE_SERVER_GET_ID :end-before: //!
After processing the request, the server should send the reply to the client with the related request attached. This is done assigning the stored identifier in |WriteParams-related_sample_identity-api|.
.. literalinclude:: ../../../../code/DDSCodeTester.cpp :language: c++ :dedent: 4 :start-after: //REQUEST_REPLY_EXAMPLE_SERVER_SEND_REPLY :end-before: //!
When the client application receives a reply (for example through |DataReaderListener::on_data_available-api|), the client application should identify if the received reply is the one expected for its request. For this the client application has to compare the stored |SampleIdentity-api| with the incoming |SampleInfo::related_sample_identity-api|.
.. literalinclude:: ../../../../code/DDSCodeTester.cpp :language: c++ :dedent: 4 :start-after: //REQUEST_REPLY_EXAMPLE_CLIENT_RECEIVE_REPLY :end-before: //!