UDP bind: Address already in use

2019-09-12 06:27发布

I have no knowledge in node.js.

I am sending UDP packets in C++ and I want to show them in node.js.

The problem is that both try to occupy the IP/port. Depending on which one I run, the other one fails. How should I fix this problem?

main.cpp

// g++ main.cpp -o main -std=c++11 -lboost_system -pthread

#include <iostream>
#include <stdio.h>
#include <string>
#include <boost/asio.hpp>

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


int main(int argc, char* argv[])
{

    const int port=1414;
    const std::string ip="127.0.0.1";

    boost::asio::io_service io_service;
    udp::resolver resolver(io_service);

    udp::endpoint client_endpoint = *resolver.resolve({udp::v4(), ip, std::to_string(port)});
    udp::socket socket(io_service, udp::endpoint(udp::v4(), port));
    boost::asio::socket_base::reuse_address option(true);
    socket.set_option(option);

    std::string data;
    for(long i=0;true;i++)
    {
        data=std::to_string(i+1)+"th packet";
        socket.send_to(boost::asio::buffer(data.c_str(), data.length()+1), client_endpoint);
        usleep(10);
    }

    return 0;
}

app.js

var PORT = 1414;
var HOST = '127.0.0.1';

var dgram = require('dgram');
var server = dgram.createSocket('udp4');

server.on('listening', function () {
    var address = server.address();
    console.log('UDP Server listening on ' + address.address + ":" + address.port);
});

server.on('message', function (message, remote) {
    console.log(remote.address + ':' + remote.port +' - ' + message);

});

server.bind(PORT, HOST);

If I run the C++ file and then the js one, the error is this:

events.js:160
      throw er; // Unhandled 'error' event
      ^

Error: bind EADDRINUSE 127.0.0.1:1414
    at Object.exports._errnoException (util.js:1012:11)
    at exports._exceptionWithHostPort (util.js:1035:20)
    at dgram.js:221:18
    at _combinedTickCallback (internal/process/next_tick.js:77:11)
    at process._tickCallback (internal/process/next_tick.js:98:9)
    at Module.runMain (module.js:577:11)
    at run (bootstrap_node.js:352:7)
    at startup (bootstrap_node.js:144:9)
    at bootstrap_node.js:467:3

While, if I run the js file first and then the C++ one, I receive:

terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::system::system_error> >'
  what():  bind: Address already in use
Aborted (core dumped)

2条回答
Animai°情兽
2楼-- · 2019-09-12 06:58

You need to set reuseAddr: true when creating your socket:

var server = dgram.createSocket({ type: 'udp4', reuseAddr: true });

You will also need to change how you create your socket on the C++ side. Currently the udp::socket constructor signature you're using will cause the socket to bind immediately. Unfortunately, you need to set the reuse_address option first before binding. To do that, try this intead:

udp::socket socket(io_service, udp::v4());
socket.set_option(boost::asio::socket_base::reuse_address(true));
socket.bind(udp::endpoint(udp::v4(), port));
查看更多
女痞
3楼-- · 2019-09-12 07:08

What @mscdex wrote is correct, but what @EJP's suggested is a more standard way of doing what you're (I believe) trying to accomplish.

That is, you normally have only the server on a well known port such as 1414 and clients usually start on any random port that is not already used.

To do that, you don't need to change your js code, and only change this part of c++ code:

udp::endpoint client_endpoint
    = *resolver.resolve({udp::v4(), ip, std::to_string(port)});
udp::socket socket(io_service, udp::endpoint(udp::v4(), port));
boost::asio::socket_base::reuse_address option(true);
socket.set_option(option);

to:

udp::endpoint client_endpoint
    = *resolver.resolve({udp::v4(), ip, std::to_string(port)});
// Passing 0 as the port argument will tell the system to
// pick a random port for you.
udp::socket socket(io_service, udp::endpoint(udp::v4(), 0));
查看更多
登录 后发表回答