Examples on how to use the request-reply API .
Examples on how to use the request-reply API .
Request-Reply code examples.
Request-Reply Examples
Requesters and Repliers provide a way to use the Request-Reply communication pattern on top of the DDS entities. An application uses a Requester to send requests to a Replier; another application using a Replier receives a request and can send one or more replies for that request. The Requester that sent the request (and only that one) will receive the reply (or replies).
DDS Types
RTI Connext uses DDS data types for sending and receiving requests and replies. Valid types are those generated by the rtiddsgen code generator, the DDS built-in types, and DynamicData
. Refer to the Core Libraries User's Manual and the following links for more information:
Set up
Requester: sending requests and receiving replies
Replier: receiving requests and sending replies
Error handling
- Note
- To use Request-Reply you need to build and link your application with the additional
rticonnextmsgcpp
library and include ndds/ndds_requestreply_cpp.h
.
Requester Creation
- Setting up a participant
- Creating a Requester
domain_id, DDS::PARTICIPANT_QOS_DEFAULT,
NULL, DDS::STATUS_MASK_NONE);
Requester<Foo, Bar> * requester =
new Requester<Foo, Bar>(participant, "TestService");
virtual DDSDomainParticipant * create_participant(DDS_DomainId_t domainId, const DDS_DomainParticipantQos &qos, DDSDomainParticipantListener *listener, DDS_StatusMask mask)=0
Creates a new DDSDomainParticipant object.
static DDSDomainParticipantFactory * get_instance()
Gets the singleton instance of this class.
<<interface>> Container for all DDSDomainEntity objects.
Definition: domain.ifcxx:191
Namespace for Connext.
Definition: entity_params.ifcxx:38
Creating a Requester with optional parameters
- Setting up a participant
- Creating a Requester with additional parameters
domain_id, DDS::PARTICIPANT_QOS_DEFAULT,
NULL, DDS::STATUS_MASK_NONE);
RequesterParams requester_params(participant);
requester_params.service_name("TestService");
requester_params.qos_profile(
"RequestReplyExampleProfiles", "RequesterExampleProfile");
Requester<Foo, Bar> * requester = new Requester<Foo, Bar>(requester_params);
- See also
- Requester Creation
-
Configuring Request-Reply QoS profiles
Basic Requester example
Taking loaned samples
- Requester Creation
- Get iterator to loaned replies (no copies)
LoanedSamples<Bar> replies = requester->take_replies();
for (LoanedSamples<Bar>::const_iterator it = replies.begin();
it != replies.end();
++it) {
if (it->info().valid_data) {
std::cout << "Received reply: " << it->data().message << std::endl;
}
}
- See also
- Basic Requester example
-
Basic Replier example
-
Taking samples by copy
Taking samples by copy
- Requester Creation
- Get copies of the replies:
LoanedSamples<Bar> replies = requester->take_replies();
std::list<Sample<Bar> > my_list;
std::copy(replies.begin(), replies.end(), std::back_inserter(my_list));
std::vector<Bar> my_vector;
std::copy(
std::back_inserter(my_vector));
ValidSampleIterator< T, IsConst > make_valid_sample_iterator(SampleIterator< T, IsConst > related_iterator)
Creates an iterator that only returns valid samples.
Definition: xmq_cpp.1.0/interface/infrastructure.ifcxx:2744
- See also
- Basic Replier example
-
Taking loaned samples
Correlating requests and replies
- Requester Creation
- Example 1) Waiting for a reply to a specific request
WriteSample<Foo> request1, request2;
strcpy(request1.data().message, "Request 1");
strcpy(request2.data().message, "Request 2");
requester->send_request(request1);
requester->send_request(request2);
Sample<Bar> reply;
bool received = requester->wait_for_replies(
1, MAX_WAIT, request2.identity());
if (!received) {
std::cout << "Did not receive reply for request 2" << std::endl;
return;
}
requester->take_reply(reply, request2.identity());
if (reply.related_identity() != request2.identity()) {
throw std::runtime_error("postcondition failed");
}
if (reply.info().valid_data) {
std::cout << "Received reply for request 2: "
<< reply.data().message << std::endl;
}
received = requester->wait_for_replies(1, MAX_WAIT, request1.identity());
if (!received) {
std::cout << "Did not receive reply for request 1" << std::endl;
return;
}
requester->take_reply(reply, request1.identity());
if (reply.related_identity() != request1.identity()) {
throw std::runtime_error("postcondition failed");
}
if (reply.info().valid_data) {
std::cout << "Received reply for request 1: "
<< reply.data().message << std::endl;
}
- Example 2) Correlating a reply after receiving it
WriteSample<Foo> request1, request2;
strcpy(request1.data().message, "Request 1");
strcpy(request2.data().message, "Request 2");
requester->send_request(request1);
requester->send_request(request2);
bool received = requester->wait_for_replies(2, MAX_WAIT);
if (!received) {
std::cout << "Replies not received" << std::endl;
return;
}
LoanedSamples<Bar>::iterator it;
LoanedSamples<Bar> replies = requester->take_replies();
it = std::find_if(replies.begin(), replies.end(),
IsReplyRelatedPredicate<Bar>(request1.identity()));
if (it != replies.end()) {
std::cout << "Received reply for request 1: "
<< it->data().message << std::endl;
}
it = std::find_if(replies.begin(), replies.end(),
IsReplyRelatedPredicate<Bar>(request2.identity()));
if (it != replies.end()) {
std::cout << "Received reply for request 2: "
<< it->data().message << std::endl;
}
- See also
- Basic Requester example
-
Basic Replier example
Basic Requester example using SampleRef
This example is similar to Basic Requester example except it uses a SampleRef instance instead of a Sample instance.
Creating a Replier
- Setting up a participant
- Create a Replier
domain_id, DDS::PARTICIPANT_QOS_DEFAULT,
NULL, DDS::STATUS_MASK_NONE);
Replier<Foo, Bar> * replier =
new Replier<Foo, Bar>(participant, "TestService");
Basic Replier example
- Creating a Replier
- Basic Replier example
Sample<Foo> request;
bool received = replier->receive_request(request, MAX_WAIT);
if (!received) {
std::cout << "Requests not received" << std::endl;
return false;
}
WriteSample<Bar> reply;
if (request.info().valid_data) {
sprintf(reply.data().message, "Reply for %s", request.data().message);
replier->send_reply(reply, request.identity());
}
- See also
- Basic Requester example
SimpleReplier example
Error handling example
- Catching an exception from the request-reply API
WriteSample<Bar> reply;
try {
replier->send_reply(reply, invalid_request_id);
} catch (const BadParameterException& ex) {
std::cout << "Exception while sending reply: "
<< ex.what() << std::endl;
}
try {
replier->send_reply(reply, invalid_request_id);
} catch (const std::exception& ex) {
std::cout << "Exception while sending request: "
<< ex.what() << std::endl;
}
static NDDSConfigLogger * get_instance()
Get the singleton instance of this type.
void set_verbosity(NDDS_Config_LogVerbosity verbosity)
Set the verbosity at which RTI Connext will log diagnostic information.
@ NDDS_CONFIG_LOG_VERBOSITY_WARNING
Both error and warning messages will be logged.
Definition: ndds_config_c.ifc:172
Type definition for a Sample Identity.
Definition: infrastructure.ifc:9404
Configuring Request-Reply QoS profiles
If you do not specify your own QoS parameters (in connext::RequesterParams and connext::ReplierParams), a connext::Requester and connext::Replier are created using a default configuration. That configuration is equivalent to the one in the following QoS profile called "default":
<?xml version="1.0" encoding="UTF-8"?>
<dds xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="file:////rti/jenkins/workspace/connextdds_htmldocs_support_connextdds_7.3.0/build/nddsgen.2.0/resource/schema/rti_dds_qos_profiles.xsd">
<qos_library name="HelloWorld_Library">
<qos_profile name="HelloWorld_Profile" base_name="BuiltinQosLib::Generic.StrictReliable" is_default_qos="true">
<datawriter_qos>
<publication_name>
<name>HelloWorldDataWriter</name>
</publication_name>
</datawriter_qos>
<datareader_qos>
<subscription_name>
<name>HelloWorldDataReader</name>
</subscription_name>
</datareader_qos>
<domain_participant_qos>
<participant_name>
<name>HelloWorldParticipant</name>
<role_name>HelloWorldParticipantRole</role_name>
</participant_name>
</domain_participant_qos>
</qos_profile>
</qos_library>
</dds>
You can use the profile called "RequesterExampleProfile", which modifies some parameters from the default. The example Creating a Requester with optional parameters shows how to create a connext::Requester using this profile.
- See also
- Creating a Requester with optional parameters
-
Configuring QoS Profiles with XML