I have a fairly large application that works as desired on Linux. I've recently compiled it on Windows 7 using VC2012 and boost asio 1.52 and run into a strange issue:
An async_receive_from
followed by an async_send_to
on the same UDP socket results in the read completion handler being called with boost::system::error_code
10061:
No connection could be made because the target machine actively refused it
if the send destination is another port on the local host. If the packet is sent to another machine, the read completion handler is not called. After the read completion handler, the write completion handler is called with no error.
The following code replicates the issue:
#include <iostream>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
using namespace std;
using namespace boost::asio;
void read_completion_handler(const boost::system::error_code& ec, std::size_t bytes_received)
{
if (!ec)
cout << "Received " << bytes_received << " successfully" << endl;
else
cout << "Error: " << ec.message() << endl;
}
void write_completion_handler(const boost::system::error_code& ec, std::size_t bytes_transferred)
{
if (!ec)
cout << "Wrote " << bytes_transferred << " successfully" << endl;
else
cout << "Error: " << ec.message() << endl;
}
int main(int argc, char** argv)
{
enum
{
max_length = 1500,
out_length = 100
};
// buffer for incoming data
char data[max_length];
// outgoing data
char out_data[out_length];
// sender endpoint
ip::udp::endpoint sender_endpoint;
// for sending packets: if this localhost, the error occurs
ip::udp::endpoint destination(ip::address::from_string("127.0.0.1"), 5004);
io_service ioService;
ip::udp::socket socket(ioService, ip::udp::endpoint(ip::udp::v4(), 49170));
socket.async_receive_from(
buffer(data, max_length), sender_endpoint,
boost::bind(&read_completion_handler,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
socket.async_send_to( boost::asio::buffer(out_data, out_length),
destination,
boost::bind(&write_completion_handler,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
ioService.run();
cout << "Done" << endl;
return 0;
}
On linux this is never an issue. Does anyone have an explanation? As far as I know, simultaneous reads and writes on the same socket should be ok or is this not the case on Windows? Why the change in behaviour if localhost is the destination?
Yes, it's about 6 months after you asked this question. I'm not even sure how I ended up here. I ran into this problem myself -- but the good news is that it's not a problem.
Some machines return a Destination Unreachable message through ICMP when they aren't listening on the port you sent your message to. Asio translates this to boost::system::errc::connection_refused and/or boost::system::errc::connection_reset. This is a meaningless error since UDP is connectionless. You can safely ignore these two error codes in your async_receive_from handler (ie, if you get one of these errors returned, just call async_receive_from again).