简体   繁体   中英

boost:asio async_receive_from behaves synchronously

In the code below, the asynch_receive_from behaves synchronously. It doesn't come back until data is received. A look at the log at the end indicates this. This may not be that obvious at first because there's a fairly high rate of data coming in. But when there's not data, only one second heartbeat messages, the return out of these asynch calls is on the order of one second as well.

The question is why aren't these asynch calls returning immediately (within a few micros), and with no bytes read?

I thought that maybe having other items in the run queue would facilitate the process, thinking that if there's nothing on the queue to run that io_services would turn the asynch function into a synch function since there's nothing else for it to do yet. But I added the 2 posts ahead of the asynch call which, I would believe, put something into the run queue ahead of the asynch call. But that didn't seem to make a difference.

Any help would be appreciated. I am new to the boost::asio library.

void receiver::handle_receive_from(const boost::system::error_code& error,
      size_t bytes_recvd)
{
    static char logBuf[128];    
    string dStr;
    int rVal;
    unsigned int seqNo;

    sprintf_s(logBuf, sizeof(logBuf), "BytesRead:%d", bytes_recvd);
    MyLog(logBuf);
    MyLog("1"); 
    MyLog("2");
    iosP->post(boost::bind(&receiver::postTestHandler, this));
    iosP->post(boost::bind(&receiver::postTestHandler, this));
    socket_.async_receive_from(
                boost::asio::buffer(data_, max_length), sender_endpoint_,
                boost::bind(&receiver::handle_receive_fromTwo, this,
                boost::asio::placeholders::error,
                boost::asio::placeholders::bytes_transferred));     

    MyLog("3");

}

void receiver::handle_receive_fromTwo(const boost::system::error_code& error, size_t bytes_recvd)
{
    char logBuf[128];

    sprintf_s(logBuf, sizeof(logBuf), "Two BytesRead:%d", bytes_recvd);
    MyLog(logBuf);

    MyLog("1-Two"); 
    MyLog("2-Two");
    iosP->post(boost::bind(&receiver::postTestHandler, this));
    iosP->post(boost::bind(&receiver::postTestHandler, this));
    socket_.async_receive_from(
                boost::asio::buffer(data_, max_length), sender_endpoint_,
                boost::bind(&receiver::handle_receive_from, this,
                boost::asio::placeholders::error,
                boost::asio::placeholders::bytes_transferred));         


    MyLog("3-Two");

}

void receiver::postTestHandler()
{   
    int count(0);
    MyLog("***postTestHandler entry***");
    printf("***postTestHandler entry***\n");
    printf("Exiting postTestHandler\n");
    MyLog("Exiting postTestHandler");
}

Log snippet

[11:57:51.653647]BytesRead:16
[11:57:51.653660]1
[11:57:51.653662]2
[11:57:51.653692]3
[11:57:51.653697]***postTestHandler entry***
[11:57:51.654310]Exiting postTestHandler
[11:57:51.654315]***postTestHandler entry***
[11:57:51.654657]Exiting postTestHandler
[11:57:51.727494]Two BytesRead:67
[11:57:51.727503]1-Two
[11:57:51.727506]2-Two
[11:57:51.727524]3-Two
[11:57:51.727529]***postTestHandler entry***
[11:57:51.728060]Exiting postTestHandler
[11:57:51.728065]***postTestHandler entry***
[11:57:51.728407]Exiting postTestHandler
[11:57:52.438916]BytesRead:67
[11:57:52.438929]1
[11:57:52.438932]2
[11:57:52.438961]3
[11:57:52.438965]***postTestHandler entry***
[11:57:52.439568]Exiting postTestHandler
[11:57:52.439573]***postTestHandler entry***
[11:57:52.439914]Exiting postTestHandler
[11:57:52.581333]Two BytesRead:67
[11:57:52.581346]1-Two
[11:57:52.581349]2-Two
[11:57:52.581375]3-Two
[11:57:52.581381]***postTestHandler entry***
[11:57:52.582011]Exiting postTestHandler
[11:57:52.582016]***postTestHandler entry***
[11:57:52.582358]Exiting postTestHandler
[11:57:52.582364]BytesRead:67
[11:57:52.582367]1
[11:57:52.582370]2
[11:57:52.582377]3
[11:57:52.582381]***postTestHandler entry***
[11:57:52.582717]Exiting postTestHandler
[11:57:52.582722]***postTestHandler entry***
[11:57:52.583055]Exiting postTestHandler
[11:57:52.583061]Two BytesRead:67
[11:57:52.583064]1-Two
[11:57:52.583066]2-Two
[11:57:52.583077]3-Two
[11:57:52.583081]***postTestHandler entry***
[11:57:52.583418]Exiting postTestHandler
[11:57:52.583423]***postTestHandler entry***
[11:57:52.583755]Exiting postTestHandler
[11:57:52.616525]BytesRead:67
[11:57:52.616531]1
[11:57:52.616533]2
[11:57:52.616549]3
[11:57:52.616553]***postTestHandler entry***
[11:57:52.617015]Exiting postTestHandler
[11:57:52.617020]***postTestHandler entry***
[11:57:52.617362]Exiting postTestHandler

Not sure if you're still having this issue, but it will block after you call io_service.run() because it will indefinitely be looking for packets that it has received. If you'd like it to check for callbacks, but not block if there aren't any, then use io_service.poll(). If you'd like it to execute exactly one callback (if there are one or more requests) then use io_service.poll_one().

Not sure if this is your problem, or if you still have this issue (I know this question is very old), but good luck!

edit (in response to your comment):

If you use io_service.run(), then that thread will be forever dedicated to handling asio callbacks. However, if you use io_service.poll(), then you can handle callbacks when you want to and then do something else in the meantime. io_service.poll() is in no way faster than io_service.run(), it just gives you the ability to handle callbacks whenever you want to, rather than always indefinitely.

You could probably picture io_service.run() to be implemented like this:

void IOService::run()
{
    while (true)
    {
        poll();
    }
}

Note that it is not implemented like this. But this might clear up the idea of what run and poll are doing.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM