I am trying to get data from a device which sends data using UDP using the code below:
#include "Boost.UdpLayer.h"
#include <iostream>
#include <boost/asio.hpp>
using namespace boost::asio;
UdpLayer::UdpLayer(const std::string _ip, const int _port, Bugeye* instance)
{
ip = _ip;
port = _port;
device = instance;
Start();
}
void UdpLayer::Send(const char* message, const int length)
{
if (!boostSocket)
return;
boostSocket->send_to(buffer(message, length), deviceEndpoint);
std::cout << "Interrogated on port " << deviceEndpoint.port() << std::endl;
std::cout << "My local port is " << GetLocalPort() << std::endl;
std::fill(recv_buffer.begin(), recv_buffer.end(), 0);
ip::udp::endpoint rep;
try
{
volatile int sz = boostSocket->receive_from(buffer(recv_buffer), rep);
if(sz > 0)
{
std::cout << "Received reply on port " << rep.port() << std::endl;
device->ParsePacket(recv_buffer, sz);
}
}
catch (std::exception& ex)
{
std::cout << std::endl << "Exception " << ex.what() << std::endl << std::endl;
}
}
int UdpLayer::GetLocalPort() const
{
return boostSocket->local_endpoint().port();
}
void UdpLayer::Start()
{
boostSocket = std::make_shared<ip::udp::socket>(io_service);
deviceEndpoint = ip::udp::endpoint(ip::address::from_string(ip), port);
io_service.run();
boostSocket->open(ip::udp::v4());
boostSocket->connect(deviceEndpoint);
boostSocket->set_option(boost::asio::detail::socket_option::integer<SOL_SOCKET, SO_RCVTIMEO>{ 2000 });
}
void UdpLayer::Terminate()
{
if (boostSocket)
{
boostSocket->shutdown(ip::udp::socket::shutdown_both);
boostSocket.reset();
}
io_service.stop();
}
I have used Wireshark to sniff packets in and out the device and the device is replying appropriately.
There's a MFC (32 bit) application which relies on CAsyncReceive which gets packets properly. I have checked packets sent by the MFC application and packets sent by the code above and both match.
I have tried porting code from Boost to Winsock2 without any success. I am unsure if any flags must be set so this packet will make it's way through device->ParsePacket. Payloads are small in size: 95 bytes so I believe a buffer overrun is not the case here.
I also tried to disable Windows Firewall entirely - no success. I wonder if there's anything else that must be done like setting an option so this will work properly.
I was able to fix it by creating a local separete server bound to a free port. This port is sent to the device as part of the communication packet. The device then uses this port number to reply back.