2017-10-05 247 views
1

我正在努力解决数小时问题: 我想连接一个boost asio udo套接字到端点。在IPv4中这样做没有问题。但是如果我尝试在IPv6中做同样的事情,我会得到一个错误代码“无效参数”。boost asio udp套接字连接无效参数(IPv6)

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

struct UdpConnectionParams 
{ 
    udp::endpoint m_localEndpoint; 
    udp::endpoint m_remoteEndpoint; 
} 

boost::system::error_code setupUdpConnection(udp::socket& p_socket, const UdpConnectionParams& p_params) 
{ 
    // close socket 
    boost::system::error_code h_ignoreError; 
    p_socket.close(h_ignoreError); 
    // variables for kind of UDP connection 
    udp h_protocol(udp::v4()); 
    bool h_shallBind{false}; 
    bool h_shallConnect{false}; 

    // determine kind of connection 
    if(p_params.m_localEndpoint != udp::endpoint()) 
    { 
     h_protocol = p_params.m_localEndpoint.protocol(); 
     h_shallBind = true; 
    } 
    if(p_params.m_remoteEndpoint != udp::endpoint()) 
    { 
     h_protocol = p_params.m_remoteEndpoint.protocol(); 
     h_shallConnect = true; 
    } 
    if(!h_shallBind && !h_shallConnect) 
    { 
     // no endpoint specified, return error 
     return boost::system::error_code(ENetworkErrorCode::NO_ENDPOINT_SPECIFIED, NetworkErrorCategory::getCategory()); 
    } 

    try 
    { 
     p_socket.open(h_protocol); 
     //bind socket to certain endpoint 
     if(h_shallBind) 
     { 
      p_socket.bind(p_params.m_localEndpoint); 
     } 
     //connect socket to client. Thus it is possible to use p_socket.send() 
     if(h_shallConnect) 
     { 
      p_socket.connect(p_params.m_remoteEndpoint); 
     } 
    } 
    catch (boost::system::system_error& h_error) 
    { 
     p_socket.close(h_ignoreError); 
     return h_error.code(); 
    } 
    // no error 
    return boost::system::error_code(); 
} 

int main() 
{ 
    boost::asio::io_service service; 
    udp::socket socket(service); 
    boost::system::error_code error; 
    UdpConnectionParams params; 
    params.m_localEndpoint = udp::endpoint(udp::v6(), 55555); 
    params.m_remoteEndpoint = udp::endpoint(boost::asio::ip::address_v6::from_string("ff01::101"), 55555); 
    error = setupUdpConnection(socket, params); 
    cout << error << error.message() << endl; // "invalid argument" 
    return 0; 
} 

我没有得到任何错误的唯一方法是使用本地主机IP地址(:: 1)。如果我将套接字绑定到端点,则没有区别。 我在做什么错?

回答

2

我在做什么错?

问题是,您没有在使用的IPv6地址中指定接口索引/范围。 IPv6多播地址需要指定范围,以便网络堆栈将知道您的计算机的哪个本地网络接口将IP地址与之关联。即

代替:

boost::asio::ip::address_v6::from_string("ff01::101"), 55555); 

你需要的东西,如:%符号后

boost::asio::ip::address_v6::from_string("ff01::101%eth0"), 55555); 

(后缀将取决于您要使用的网络接口的名称,当然)

(注意,“ff01 ::”前缀是针对节点本地IPv6多播组的,这意味着您的UDP数据包只能发送到运行在同一台计算机上的其他程序。你的意图是什么,那么伟大;另一方面,如果你想让你的UDP数据包到达同一局域网中的其他计算机,你需要使用“ff02 ::”或“ff12 ::”前缀(ff02 ::将用于一个知名的,已知的多播地址,ff12 ::将用于临时多播地址)。有关详细信息,请参阅the Wikipedia page上的“组播地址范围”表)

+0

谢谢!那么,我无法使用“ff01 :: 101%eth0”或“ff01 :: 101%lo”,但它可以与“ff12 :: 1%eth0”一起使用。将套接字连接到节点本地IPv6多播组需要什么?如果我不连接套接字,但为什么不使用“send_to”和“receive_from”方法来解决此问题? – Christi258

+0

ff11 :: 1%eth0(或ff11 :: 11%lo等)将是节点本地等效组。至于它为什么与send_to()和receive_from()协同工作,但与connect()不同,我不知道。 –