2017-10-05 16 views
1

私は何時間も問題を抱えています: ブーストasio udoソケットをエンドポイントに接続したいとします。これをIPv4で行うことは問題ありません。しかし、私がIPv6で同じことをしようとすると、私はエラーコード "無効な引数"を取得します。boost asio udp socket connect(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パケットが同じLAN上の他のコンピュータに届くようにしたい場合は、代わりに "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()では動作しない理由は分かりません。 –

関連する問題