Data sporadically not arriving (Request Reply)

5 posts / 0 new
Last post
Offline
Joined: 03/06/2015
Posts: 7
Data sporadically not arriving (Request Reply)

I tried the Request-Reply-Example which is in the C++ example folder of RTI 5.1.0.

If I use the Requester in a command window (Ubuntu 12.04) and the Replier in another command windows on the same machine,

the Requester sporadically (can be the second time or the 20. time I send a request) doesn't get the data from the Replier. But the Replier gets the request and says that he replied (in the command window).

 

If I uncomment the "return -1" in the catch exception and tell the Requester to resend the request if it didn't get the reply, its gets the next reply, as it should.

 

If I use a second computer to run the Replier and the first computer to only run the Requester, this error doesn't happen. Thats very strange, because this way the example programs can't have an error.

 

What can cause this behavior of not receiving a reply, where the Replier application says it has send the reply, but the Requester doesn't get it?

 

Thanks in advance.

Offline
Joined: 04/02/2013
Posts: 95

Hi Mathias,

I wonder if you might be running into the following corner case. A requester and a replier are made of one DataWriter and one DataReader each. Your Requester DataWriter could be discovering the Replier DataReader and delivering the request. But the request could arrive before the Replier DataWriter (used to send the reply) discovers the Requester DataReader. Therefore the reply, wouldn't be delivered.

You can modify the Requester and Replier examples to ensure that all discovery has completed. This is a snippet in Java for the Requester:

requester.getRequestDataWriter().get_matched_subscriptions(subcriptions);
requester.getReplyDataReader().get_matched_publications(publications);
while (subcriptions.isEmpty() || publications.isEmpty()) {
    requester.getRequestDataWriter().get_matched_subscriptions(subcriptions);
    requester.getReplyDataReader().get_matched_publications(publications);
    Thread.sleep(50);
} 

 The Replier code will be similar.

I hope this helps.

Alex

 

Offline
Joined: 03/06/2015
Posts: 7

Thank you Alex,

I thought about something very similar and I think that what you said must be the reason for my problem..

I don't have much knowledge about Java. Could you provide a short code snippet of how to do the same in C++?

 

Thanks in advance.

Mathias

Offline
Joined: 04/02/2013
Posts: 95

Mathias,

You can use this function for the Requester

template <typename Request, typename Reply>
void wait_for_replier(connext::Requester<Request, Reply>& requester)
{
    using namespace DDS;

    DataWriter * writer = requester.get_request_datawriter();
    DataReader * reader = requester.get_request_datareader();

    InstanceHandleSeq sub_handles, pub_handles;
    const Duration_t sleep_time = {0, 50000000}; // 50 ms
    
    writer->get_matched_subscriptions(sub_handles);
    reader->get_matched_publications(pub_handles);
    while(sub_handles.length() == 0 || pub_handles.length() == 0) {
        NDDSUtility::sleep(sleep_time);
        writer->get_matched_subscriptions(sub_handles);
        reader->get_matched_publications(pub_handles);
    };
}

The replier would be very similar.

This function is not perfect though. It assumes that the only DataWriters and DataReaders that you will discover are those belonging to a Replier, but your system could have other non-Replier applications subscribing. A more sofisticated function would also look at the matched subscription/publication data to check that you are discovering exactly what you want.

Offline
Joined: 03/06/2015
Posts: 7

Hello Alejandro,


thanks for the function. With some minor adaptions I was able to get it to work nearly completly.

Communication is more stable now, even if only the Requester-Side is using the function to detect the related Replier...

 

In my network setup 4 Requester exist which all request data at only one Replier.

I rewrote your function to be able to use it for the Replier, to make communication 100% stable:

code

template <typename Request, typename Reply>
    void wait_for_requester(connext::Replier<Request, Reply>& replier)
    {
        using namespace DDS;

        DataWriter * writer = replier.get_reply_datawriter();
        DataReader * reader = replier.get_request_datareader();

        InstanceHandleSeq sub_handles, pub_handles;
        const Duration_t sleep_time = {0, 50000000}; // 50 ms

        writer->get_matched_subscriptions(sub_handles);
        reader->get_matched_publications(pub_handles);
        while(sub_handles.length() == 0 || pub_handles.length() == 0) {
            std::cout << "Replier waits for established connection..." << std::endl;
            NDDSUtility::sleep(sleep_time);
            writer->get_matched_subscriptions(sub_handles);
            reader->get_matched_publications(pub_handles);
        };
    }
code 

 

But I have the following problem:

I only call the function "wait_for_replier" when I start the replier (and after that I never stop/close the replier). So now the Replier is waiting for the first subscription of a Requester, but after that (of course) it won't call "wait for replier" if there are other requesters anymore.

Therefore, only the Connection to the first Requester is 100% stable, but the other Requester don't benefit from this improvement and don't get this stability enhancement.


Do you have an idea, how to always check for the subscripted Requesters?

I think in principle, the Replier would have to get a request (including data), then check if it knows the related DataWriters and Datareaders of the related Requester and after that it could send the data.

The perfect idea of using *ub_handles.length() (like on the Requester side) will not solve the problem here, I think.

Is there a way to do this?

 

Thanks in advance!

Mathias