2016-09-01 4 views
0

Я не знаю в node.js.UDP bind: Адрес уже используется

Я посылаю UDP пакеты в C++, и я хочу показать их в node.js.

Проблема в том, что оба пытаются занять IP/порт. В зависимости от того, какой я запускаю, другой не работает. Как мне исправить эту проблему?

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); 

Если я бегу C++ файл и затем js один, ошибка заключается в следующем:

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 

В то время как, если я сначала запустил файл js, а затем C++ один, я получаю ве:

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) 
+1

Использование двух различных портов. Если один из сверстников является клиентом, ему не нужен номер фиксированного порта. – EJP

+0

@EJP, Как я могу отправить данные на один порт и получить его из другого порта? – ar2015

+0

Вам не обязательно. Клиент отправляет на порт сервера и получает его в своем собственном порту. Сервер отправляет ответчика обратно на удаленный IP-порт, из которого был получен запрос. – EJP

ответ

1

Вам нужно установить reuseAddr: true при создании сокета:

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

Вам также необходимо изменить, как вы создаете сокет на стороне C++. В настоящее время подпись конструктора udp::socket, которую вы используете, вызовет немедленное связывание сокета. К сожалению, вам необходимо сначала установить опцию reuse_addressдо. Чтобы сделать это, попробуйте этот 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)); 
+0

Большое спасибо. Он работает сейчас, если я запускаю 'cpp', а затем' js'. Как исправить это с 'C++', так что я могу называть' js', а затем 'cpp'. – ar2015

+0

Я обновил свой ответ. – mscdex

2

Что @mscdex написал правильно, но то, что @ EJP предположил, является более стандартный способ делать то, что вы (я верю) пытается достичь.

То есть у вас обычно есть только сервер на хорошо известном порту, например 1414, и клиенты обычно запускаются на любом случайном порту, который еще не используется.

Чтобы сделать это, вам не нужно менять код JS, и только изменить эту часть C++ код:

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); 

к:

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)); 
Смежные вопросы