Search code examples
windowsnetwork-programmingudpboost-asio

Windows boost asio: 10061 in async_receive_from on on async_send_to


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?


Solution

  • 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).