Boost ASIO IPv6 join_group在OS X上不起作用

Boost ASIO IPv6 join_group does not work on OS X

本文关键字:OS 不起作用 group ASIO IPv6 join Boost      更新时间:2023-10-16

我正试图在OSX上打开IPv6多播侦听端口,但在尝试运行"join_group"选项时收到错误代码49。以下是导致问题的代码示例:

ip6_listen=boost::make_shared<boost::asio::ip::udp::socket>(io_service);
ip6_listen->open(boost::asio::ip::udp::v6());
ip6_listen->set_option(boost::asio::ip::udp::socket::reuse_address(true));
ip6_listen->bind(boost::asio::ip::udp::endpoint(boost::asio::ip::address_v6::any(),ANNOUNCE_PORT));
ip6_listen->set_option(boost::asio::ip::multicast::join_group(boost::asio::ip::address_v6::from_string("FF01::AC22"))); //Throws error "49"

目前尚不清楚为什么这会引发错误,因为它在Windows和Linux上运行正常。为什么这个错误只发生在OSX上?

在某些情况下,操作系统无法自动确定用于加入组的接口。您可以手动设置接口索引(文档):

ip6_listen->set_option(boost::asio::ip::multicast::outbound_interface(0);

至于如何获得接口索引,您可以使用以下代码:

#include <arpa/inet.h>
#include <ifaddrs.h>
#include <iostream>
#include <map>
#include <net/if.h>
#include <sys/types.h>
std::vector<uint32_t> get_v6_ifindices {
    std::vector<uint32_t> res;
    ifaddrs *ifs;
    if (getifaddrs(&ifs)) {
        std::cerr << "Error enumerating interfaces: " << errno << 'n';
        return res;
    }
    for (auto addr = ifs; addr != nullptr; addr = addr->ifa_next) {
        // No address? Skip.
        if (addr->ifa_addr == nullptr) continue;
        // Interface doesn't support multicast? Skip.
        if (!(addr->ifa_flags & IFF_MULTICAST)) continue;
        // Interface isn't active? Skip.
        if (!(addr->ifa_flags & IFF_UP)) continue;
        uint32_t idx = if_nametoindex(addr->ifa_name);
        ifaces[idx].name = addr->
        switch (addr->ifa_addr->sa_family) {
        case AF_INET: auto v4addr = ntohl(((sockaddr_in *)addr->ifa_addr)->sin_addr.s_addr); break;
        case AF_INET6: {
            res.push_back(idx);
            auto sa_in6 = (sockaddr_in6 *)addr->ifa_addr;
            auto v6addr = (const unsigned char *)&sa_in6->sin6_addr;
        }
#ifdef __APPLE__
        case AF_CCITT: break;
        case AF_LINK: break;
#else
        case AF_PACKET: break;
#endif
        default: std::clog << "Unknown interface type " << static_cast<int>(addr->ifa_addr->sa_family) << 'n';
        }
    }
    freeifaddrs(ifs);
    return res;
}