Reputation: 23939
I've written some asio-based networking classes, and they work as expected as long as they are run in separate processes. In the process of improving my test coverage, I've run into a case where the receiver will usually stop receiving data. Since my (CxxTest) test suite is a single application,
I've thrown the code up here, in a gist, it's pretty short, but the "gist" of it is:
create endpoint (127.0.0.1:54321, shared by rx/tx)
create service
create tx socket
open
set reusable(true)
set broadcast(true)
create rx socket
open
bind to endpoint
async_receive...
create thread(io_service::run)
send data several times
wait a few seconds
io_service::stop
thread::join
My receive
function just dumps the new data into a vector and stores it, it also barks out a print statement with how many bytes it received. When I run this, I get 1 receive
call with an expected amount of data, sometimes I get 2, and very rarely I've gotten 3.
Now, when I rip this file in half, one only doing the transmit side, the other only doing the receive side, it works great. Absolutely no changes other than removing each part's irrelevant contributions.
I have watched in WireShark, and all of the transmits are happening as expected, and since they're supposed to be synchronous, that makes sense to me. It's as if the receive handler isn't seeing anything new come in, so it just sits quietly. How am I missing the data? I'm new to asio, so I hope I'm just doing something obviously dumb!
Upvotes: 1
Views: 2910
Reputation: 5334
OK second try :D but this time I checked it.
Your problem is that you are using the same endpoint for send and receive. Also I found this:
In general, it is safe to make concurrent use of distinct objects, but unsafe to make concurrent use of a single object. However, types such as io_service provide a stronger guarantee that it is safe to use a single object concurrently.
So create one endpoint for your txsock
and one for rxsock
-> sending to send_end/ receiving from rec_end I got this result.
send(2006)
receive(2006)
receive(2006)
send(2006)
receive(2006)
send(2006)
receive(2006)
send(2006)
send(2006)
receive(2006)
receive(2006)
send(2006)
send(2006)
receive(2006)
receive(2006)
send(2006)
received 8 packet(s) total
receive(0)
receive error: The I/O operation has been aborted because of either a thread exit or an application request
...
ba::ip::udp::endpoint send_end;
ba::ip::udp::endpoint rec_end;
send_end = ba::ip::udp::endpoint(address, 54321);
rec_end = ba::ip::udp::endpoint(address, 54321);
// ...
rxsock->bind(rec_end);
// in go and receive
rxsock->async_receive_from(ba::buffer(buffer, BUF_SZ), rec_end,
boost::bind(receive, ba::placeholders::error, ba::placeholders::bytes_transferred));
// ...
std::size_t sz = socket.send_to(b.data(), send_end);
async_receive_from
by async_receive
it also works (on my machine) without adding an endpoint.send_to
by send
and connect the txsock to the endpoint.Upvotes: 1