Boost::asio UDP Broadcast with ephemeral port

OcularProgrammer

I'm having trouble with udp broadcast transactions under boost::asio, related to the following code snippet. Since I'm trying to broadcast in this instance, so deviceIP = "255.255.255.255". devicePort is a specified management port for my device. I want to use an ephemeral local port, so I would prefer if at all possible not to have to socket.bind() after the connection, and the code supports this for unicast by setting localPort = 0.

boost::asio::ip::address_v4 targetIP = boost::asio::ip::address_v4::from_string(deviceIP);
m_targetEndPoint = boost::asio::ip::udp::endpoint(targetIP, devicePort);

m_ioServicePtr = boost::shared_ptr<boost::asio::io_service>(new boost::asio::io_service);
m_socketPtr = boost::shared_ptr<boost::asio::ip::udp::socket>(new boost::asio::ip::udp::socket(*m_ioServicePtr));
m_socketPtr->open(m_targetEndPoint.protocol());

m_socketPtr->set_option(boost::asio::socket_base::broadcast(true));

// If no local port is specified, default parameter is 0
// If local port is specified, bind to that port.
if(localPort != 0)
{
  boost::asio::ip::udp::endpoint localEndpoint(boost::asio::ip::address_v4::any(), localPort);
  m_socketPtr->bind(localEndpoint);
}

if(m_forceConnect)
  m_socketPtr->connect(m_targetEndPoint);

this->AsyncReceive(); // Register Asynch Recieve callback and buffer
m_socketThread = boost::shared_ptr<boost::thread>(new boost::thread(boost::bind(&MyNetworkBase::RunSocketThread, this))); // Start thread running io_service process

No matter what I do in terms of the following settings, the transmit is working fine, and I can use Wireshark to see the response packets coming back from the device as expected. These response packets are also broadcasts, as the device may be on a different subnet to the pc searching for it.

The issues are extremely strange to my mind, but are as follows:

  1. If I specify the local port and set m_forceConnect=false, everything works fine, and my recieve callback fires appropriately.
  2. If I set m_forceConnect = true in the constructor, but pass in a local port of 0, the transmit works fine, but my receive callback never fires. I would assume this is because the 'target' (m_targetEndpoint) is 255.255.255.255, and since the device has a real IP, the response packet gets filtered out.
  3. (what I actually want) If m_forceConnect = false (and data is transmitted using a send_to call), and local port = 0, therefore taking an ephemeral port, my RX callback immediately fires with an error code 10022, which I believe is an "Invalid Argument" socket error.

Can anyone suggest why I can't use the connection in this manner (not explicitly bound and not explicitly connected)? I obviously don't want to use socket.connect() in this case, as I want to respond to anything I receive. I also don't want to use a predefined port, as I want the user to be able to construct multiple copies of this object without port conflicts.

As some people may have noticed, the overall aim of this is to use the same network-interface base-class to handle both the unicast and broadcast cases. Obviously for the unicast version, I can perfectly happily m_socket->connect() as I know the device's IP, and I receive the responses since they're from the connected IP address, therefore I set m_forceConnect = true, and it all just works.

As all my transmits use send_to, I have also tried to socket.connect(endpoint(ip::addressv4::any(), devicePort), but I get a 'The requested address is not valid in its context' exception when I try it.

I've tried a pretty serious hack:

boost::asio::ip::udp::endpoint localEndpoint(boost::asio::ip::address_v4::any(), m_socketPtr->local_endpoint().port());
m_socketPtr->bind(localEndpoint);

where I extract the initial ephemeral port number and attempt to bind to it, but funnily enough that throws an Invalid Argument exception when I try and bind.

OcularProgrammer

OK, I found a solution to this issue. Under linux it's not necessary, but under windows I discovered that if you are neither binding nor connecting, you must have transmitted something before you make the call to asynch_recieve_from(), the call to which is included within my this->asynch_receive() method.

My solution, make a dummy transmission of an empty string immediately before making the asynch_receive call under windows, so the modified code becomes:

m_socketPtr->set_option(boost::asio::socket_base::broadcast(true));

// If no local port is specified, default parameter is 0
// If local port is specified, bind to that port.
if(localPort != 0)
{
  boost::asio::ip::udp::endpoint localEndpoint(boost::asio::ip::address_v4::any(), localPort);
  m_socketPtr->bind(localEndpoint);
}

if(m_forceConnect)
  m_socketPtr->connect(m_targetEndPoint);

// A dummy TX is required for the socket to acquire the local port properly under windoze
// Transmitting an empty string works fine for this, but the TX must take place BEFORE the first call to Asynch_receive_from(...)
#ifdef WIN32
m_socketPtr->send_to(boost::asio::buffer("", 0), m_targetEndPoint);
#endif

this->AsyncReceive(); // Register Asynch Recieve callback and buffer
m_socketThread = boost::shared_ptr<boost::thread>(new boost::thread(boost::bind(&MyNetworkBase::RunSocketThread, this)));

It's a bit of a hack in my book, but it is a lot better than implementing all the requirements to defer the call to the asynch recieve until after the first transmission.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

How to receive a UDP broadcast sent to 255.255.255.255 using boost asio?

From Dev

How to get Ephemeral port for UDP in Erlang?

From Dev

boost::asio UDP "gather" operation

From Dev

boost asio async udp server - poor performance

From Dev

Get UDP datagram length via Boost Asio?

From Dev

boost asio async udp server - poor performance

From Dev

Boost asio udp read optimization questions

From Dev

How to use port 80 in a boost::asio server?

From Dev

Taking the port from Boost Asio socket

From Dev

Taking the port from Boost Asio socket

From Dev

boost::asio::serial_port and RTS pin

From Dev

Boost UDP multicast sender not using correct port

From Dev

boost asio multiple async_send on udp socket

From Dev

How to increase throughput of Boost ASIO, UDP client application

From Dev

How to run Boost.Asio server on port 80?

From Dev

Clear input data from serial port in boost::asio

From Dev

Can't set TCP source Port with boost asio

From Dev

Can't exclusively bind to the network port with boost asio

From Dev

Python Requests - ephemeral port exhaustion

From Dev

How to know the ephemeral port for a service?

From Dev

Python Requests - ephemeral port exhaustion

From Dev

How to resolve the real broadcast address for a IPv4 address with Boost.Asio

From Dev

What is the difference of boost asio serial_port_service and serial_port

From Dev

What is the difference of boost asio serial_port_service and serial_port

From Dev

Can a Boost.asio endpoint be used to identify a client over time for UDP connections?

From Dev

How should I find which client I am receiving from in Boost Asio in UDP?

From Dev

Boost ASIO UDP client async_receive_from calls handler even when there are no incoming messages

From Dev

Boost ASIO UDP client async_receive_from calls handler even when there are no incoming messages

From Dev

How should I find which client I am receiving from in Boost Asio in UDP?

Related Related

  1. 1

    How to receive a UDP broadcast sent to 255.255.255.255 using boost asio?

  2. 2

    How to get Ephemeral port for UDP in Erlang?

  3. 3

    boost::asio UDP "gather" operation

  4. 4

    boost asio async udp server - poor performance

  5. 5

    Get UDP datagram length via Boost Asio?

  6. 6

    boost asio async udp server - poor performance

  7. 7

    Boost asio udp read optimization questions

  8. 8

    How to use port 80 in a boost::asio server?

  9. 9

    Taking the port from Boost Asio socket

  10. 10

    Taking the port from Boost Asio socket

  11. 11

    boost::asio::serial_port and RTS pin

  12. 12

    Boost UDP multicast sender not using correct port

  13. 13

    boost asio multiple async_send on udp socket

  14. 14

    How to increase throughput of Boost ASIO, UDP client application

  15. 15

    How to run Boost.Asio server on port 80?

  16. 16

    Clear input data from serial port in boost::asio

  17. 17

    Can't set TCP source Port with boost asio

  18. 18

    Can't exclusively bind to the network port with boost asio

  19. 19

    Python Requests - ephemeral port exhaustion

  20. 20

    How to know the ephemeral port for a service?

  21. 21

    Python Requests - ephemeral port exhaustion

  22. 22

    How to resolve the real broadcast address for a IPv4 address with Boost.Asio

  23. 23

    What is the difference of boost asio serial_port_service and serial_port

  24. 24

    What is the difference of boost asio serial_port_service and serial_port

  25. 25

    Can a Boost.asio endpoint be used to identify a client over time for UDP connections?

  26. 26

    How should I find which client I am receiving from in Boost Asio in UDP?

  27. 27

    Boost ASIO UDP client async_receive_from calls handler even when there are no incoming messages

  28. 28

    Boost ASIO UDP client async_receive_from calls handler even when there are no incoming messages

  29. 29

    How should I find which client I am receiving from in Boost Asio in UDP?

HotTag

Archive