2017-10-05 244 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()不同,我不知道。 –