【问题标题】:invalid argument on boost asio udp socket connect (IPv6)boost asio udp socket connect (IPv6) 上的参数无效
【发布时间】:2017-10-05 13:56:41
【问题描述】:

我为一个问题苦苦挣扎了好几个小时: 我想将 boost asio udo 套接字连接到端点。在 IPv4 中这样做没有问题。但是如果我尝试在 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)。如果我将套接字绑定到端点,则没有区别。 我做错了什么?

【问题讨论】:

    标签: c++ boost udp ipv6 asio


    【解决方案1】:

    我做错了什么?

    问题在于您没有在您使用的 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 上的“多播地址范围”表)

    【讨论】:

    • 谢谢!好吧,我无法让它与“ff01::101%eth0”或“ff01::101%lo”一起使用,但它与“ff12::1%eth0”一起使用。将套接字连接到节点本地 IPv6 多播组需要什么?如果我不连接套接字而是使用“send_to”和“receive_from”方法,为什么我不会遇到这个问题?
    • ff11::1%eth0(或 ff11::11%lo 等)将是节点本地等效组。至于为什么它适用于send_to()和receive_from(),但不适用于connect(),我不知道。
    猜你喜欢
    • 2014-07-11
    • 1970-01-01
    • 2015-12-07
    • 2012-05-25
    • 2018-06-08
    • 1970-01-01
    • 2012-11-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多