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

时间:2014-04-17 02:59:53

标签: c++ macos sockets boost boost-asio

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

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上发生此错误?

1 个答案:

答案 0 :(得分:0)

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

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;
}