3

I've modified the UDP client code from Boost daytime client tutorial into the following:

class UDPClient
{
public:
    udp::socket* socket;
    udp::endpoint* receiver_endpoint;
    boost::array<char, 1024> recv_buffer;

    UDPClient();
    void do_receive();
    void handle_receive(const boost::system::error_code& error, size_t);
};

UDPClient::UDPClient()
{
    boost::asio::io_service io_service;

    udp::resolver resolver(io_service);
    udp::resolver::query query(udp::v4(), "127.0.0.1", "8888");
    receiver_endpoint = new udp::endpoint(*resolver.resolve(query));

    socket = new udp::socket(io_service);
    socket->open(udp::v4());

    do_receive();

    while (true)
    {
        io_service.poll();
        Sleep(1);
    }
}

void UDPClient::do_receive()
{
    socket->async_receive_from(boost::asio::buffer(recv_buffer), *receiver_endpoint,
                               boost::bind(&UDPClient::handle_receive, this,
                               boost::asio::placeholders::error,
                               boost::asio::placeholders::bytes_transferred));
}

void UDPClient::handle_receive(const boost::system::error_code& error, size_t bytes_transferred)
{
    cout << "ulala" << endl;

    if (!error || error == boost::asio::error::message_size)
        do_receive();
}

If all works out according to plan, "ulala" would only be printed if there is an incoming message. However that is not the case here... The handler gets called instantaneously and "ulala" is printed regardless of whether there is an incoming message. I've tried a few different things: swapping io_service.poll() with io_service.run() and io_service.run_one(), as well as removing Sleep(1), but none of those changes have any effect on the problem. What should I do?

Thanks in advance!

Sam Miller
  • 23,808
  • 4
  • 67
  • 87
Lai Xue
  • 1,523
  • 1
  • 15
  • 17

1 Answers1

4
socket = new udp::socket(io_service);
socket->open(udp::v4());

sets up a socket for sending to arbitrary endpoints. To receive ("listen"), use

socket = new udp::socket(io_service, udp::endpoint(udp::v4(), 8888));

Besides that, the socket and receiver_endpoint are leaked now. To fix that:

#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/array.hpp>
#include <iostream>

using boost::asio::ip::udp;

class UDPClient
{
public:
    boost::asio::io_service io_service;
    udp::socket socket;
    udp::endpoint receiver_endpoint;
    boost::array<char, 1024> recv_buffer;

    UDPClient();
    void do_receive();
    void handle_receive(const boost::system::error_code& error, size_t);
};

UDPClient::UDPClient()
    : io_service(),
      socket(io_service, {udp::v4(), 8888})
{
    do_receive();
    io_service.run();
}

void UDPClient::do_receive()
{
    socket.async_receive_from(boost::asio::buffer(recv_buffer), receiver_endpoint,
                               boost::bind(&UDPClient::handle_receive, this,
                               boost::asio::placeholders::error,
                               boost::asio::placeholders::bytes_transferred));
}

void UDPClient::handle_receive(const boost::system::error_code& error, size_t bytes_transferred)
{
    std::cout << "ulala" << std::endl;
    std::cout << "Received: '" << std::string(recv_buffer.begin(), recv_buffer.begin()+bytes_transferred) << "'\n";

    if (!error || error == boost::asio::error::message_size)
        do_receive();
}

int main()
{
    UDPClient updclient;
}

This also prints the message received (assuming it is printable). See

for a way to make it possible to handle multiple UDP requests concurrently.

Community
  • 1
  • 1
sehe
  • 374,641
  • 47
  • 450
  • 633
  • Thanks for the input man, but it doesn't seem like I could do that :\ I already have a running server that uses the expression "socket = new udp::socket(io_service, udp::endpoint(udp::v4(), 8888));", and it doesn't seem like I could have 2 programs that do this at the same time. If I use this line in the client side as well, the client crashes with the exception "Fatal program exit requested" – Lai Xue Nov 08 '14 at 21:09
  • @LaiXue please show the relevant code then. My sample is obviously running, or I wouldn't have posted it – sehe Nov 08 '14 at 21:21
  • I tried using this code in VC++ 2017, and got this error: Unhandled exception at 0x000007FEFD80A06D in SampleCpp.exe: Microsoft C++ exception: boost::exception_detail::clone_impl > at memory location 0x00000000002FE8D0. occurred. Any idea? – CaTx Mar 02 '18 at 02:27
  • @CaTx yeah, handle the exception and/or look at the cause. – sehe Mar 02 '18 at 02:46