0

I am able communicate UDP packets between a Client and Server running on localhost basically using the below code.

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

#define IPADDRESS "127.0.0.1"
#define UDP_PORT 13251

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

void Sender(std::string in) {
    boost::asio::io_service io_service;
    udp::socket socket(io_service);
    udp::endpoint remote_endpoint = udp::endpoint(address::from_string(IPADDRESS), UDP_PORT);
    socket.open(udp::v4());

    boost::system::error_code err;
    auto sent = socket.send_to(boost::asio::buffer(in), remote_endpoint, 0, err);
    socket.close();
    std::cout << "Sent bytes" << sent << "\n";
}

struct Client {
    boost::asio::io_service io_service;
    udp::socket socket{io_service};
    boost::array<char, 1024> recv_buffer;
    udp::endpoint remote_endpoint;

    int count = 3;

    void handle_receive(const boost::system::error_code& error, size_t bytes_transferred) {
        if (error) {
            std::cout << "Receive failed: " << error.message() << "\n";
            return;
        }
        std::cout << "Received: '" << std::string(recv_buffer.begin(), recv_buffer.begin()+bytes_transferred) << "' (" << error.message() << ")\n";

        if (--count > 0) {
            std::cout << "Count: " << count << "\n";
            wait();
        }
    }

    void wait() {
        socket.async_receive_from(boost::asio::buffer(recv_buffer),
            remote_endpoint,
            boost::bind(&Client::handle_receive, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
    }

    void Receiver()
    {
        socket.open(udp::v4());
        socket.bind(udp::endpoint(address::from_string(IPADDRESS), UDP_PORT));

        wait();

        std::cout << "Receiving\n";
        io_service.run();
        std::cout << "Receiver exit\n";
    }
};

int main(int argc, char *argv[])
{
    Client client;
    std::thread r([&] { client.Receiver(); });

    std::string input = argc>1? argv[1] : "hello world";
    std::cout << "Input is '" << input.c_str() << "'\nSending it to Sender Function...\n";

    for (int i = 0; i < 3; ++i) {
        std::this_thread::sleep_for(std::chrono::milliseconds(200));
        Sender(input);
    }

    r.join();
}

This works great if the client and server both are running on localhost that is 127.0.0.1. But, it does not work if client and server are running on different devices. I believe that the issue is in the configuring of udp::endpoint on both sides.

The server is running on a machine which is a router by itself. The client device connects to it and thus it is P2P where only one client and one server is involved. The local inet address of the server device is 192.168.1.1. Next, the Client connects to the Server and gets assigned with the IP 192.168.1.20.

For the UDP communication, I to assigned server side udp::endpoint to 192.168.1.1 and client side udp::endpoint to 192.168.1.20. But I still don't get UDP packets. What am I missing?

If I give the endpoint set up logic in a method then this is how it is:

boost::asio::ip::udp::endpoint remote_endpoint;
boost::asio::io_service io_service;
udp::socket udp_socket{io_service};

void PrepareUDPEndpoints(bool on_server_side) {

    std::string address;
    if (on_server_side) {
        address = "192.168.1.1";
        remote_endpoint = boost::asio::ip::udp::endpoint(boost::asio::ip::address::from_string(address), 13251);
        udp_socket.open(boost::asio::ip::udp::v4());
    } else {
        address = "192.168.1.20";
        udp_socket.open(boost::asio::ip::udp::v4());
        remote_endpoint = boost::asio::ip::udp::endpoint(boost::asio::ip::address::from_string(address), 13251);
        udp_socket.bind(remote_endpoint);
    }
}

I am getting the UDP packets "absolutely okay on localhost 127.0.0.1" but no packets at all when client and server running on 2 different machines. What am I doing wrong?

TheWaterProgrammer
  • 4,740
  • 6
  • 35
  • 102
  • Why do you bind socket at client side, when client connects to the server? Port should be bound at server, isn't it? – rafix07 Dec 18 '19 at 14:29
  • `udp_socket.bind(remote_endpoint)` should be a server side call? Not client side? – TheWaterProgrammer Dec 18 '19 at 14:31
  • If client connects to the server on given PORT, server must have bound this particular port before connecting, otherwise you won't get data at server side. – rafix07 Dec 18 '19 at 14:34
  • Given that my server local `inet` address is `192.168.1.1`. Client device connects to server and doing an `ifconfig` on client device says that it got an `inet` address of `192.168.1.20`. Give all this, how should the code in my method `PrepareUDPEndpoints` be? Note that the server side send is reporting bytes sent continiously but the client side does not get any data at all. – TheWaterProgrammer Dec 18 '19 at 14:40
  • Perhaps you'd benefit from binding your UDP ports to INADDR_ANY instead of to an explicit IP address? That would allow them to receive packets from any network device, not just from the network device with the IP address you specified in bind(). https://stackoverflow.com/questions/16508685/understanding-inaddr-any-for-socket-programming – Jeremy Friesner Dec 29 '19 at 01:08

0 Answers0