将结构 sockaddr_in6* 转换为 boost::asio::ip::address_v6

Convert struct sockaddr_in6* to boost::asio::ip::address_v6

我正在为 TCP/IP 客户端/服务器程序实现主机名/IP 地址解析器。 我可以成功地将 IPv4 地址从 sockaddr_in* 转换为 boost::asio::ip::address_v4 但我无法将 IPv6 从 struct sockaddr_in6* 转换为 boost::asio::ip::address_v6 正确:

#include <iostream>
using std::cout;

#include <netdb.h>

#include <stdexcept>
using std::domain_error;

#include <sys/socket.h>

#include <string>
using std::string;

#include <vector>
using std::vector;

#include <boost/asio.hpp>
using boost::asio::ip::address;
using boost::asio::ip::address_v4;
using boost::asio::ip::address_v6;

vector<address> getAddresses(string const &hostname)
{
    struct addrinfo req = {.ai_family = AF_UNSPEC, .ai_socktype = SOCK_STREAM};
    struct addrinfo *pai;
    int error = getaddrinfo(hostname.c_str(), nullptr, &req, &pai);
    if (error)
        throw domain_error("Could not resolve host name.");

    vector<address> addresses;

    for(struct addrinfo *info = pai; info != nullptr; info = info->ai_next) {
        if (info->ai_family == AF_INET) {
            auto ipv4socket = reinterpret_cast<struct sockaddr_in*>(info->ai_addr);
            auto ipv4addr = address_v4(htonl(ipv4socket->sin_addr.s_addr));
            addresses.emplace_back(ipv4addr);
        }
        /*
         * TODO: Implement IPv6 support.
        else {
            auto ipv6socket = reinterpret_cast<struct sockaddr_in6*>(info->ai_addr);
            auto ipv6base = reinterpret_cast<array<unsigned char, 16>>(ipv6socket->sin6_addr.__in6_u);
            auto ipv6addr = address_v6(ipv6base, ipv6socket->sin6_scope_id);
            addresses.emplace_back(ipv6addr);
        }
        */
    }

    return addresses;
}

int main()
{
    auto addresses = getAddresses("www.google.de");

    for (auto ipa : addresses)
        cout << "Address: " << ipa << "\n";

    return 0;
}

成功了:

vector<address> getAddresses(string const &hostname)
{
    struct addrinfo req = {.ai_family = AF_UNSPEC, .ai_socktype = SOCK_STREAM};
    struct addrinfo *pai;
    int error = getaddrinfo(hostname.c_str(), nullptr, &req, &pai);
    if (error)
        throw domain_error("Could not resolve host name.");

    vector<address> addresses;

    for(struct addrinfo *info = pai; info != nullptr; info = info->ai_next) {
        if (info->ai_family == AF_INET) {
            auto ipv4socket = reinterpret_cast<struct sockaddr_in*>(info->ai_addr);
            auto ipv4addr = address_v4(htonl(ipv4socket->sin_addr.s_addr));
            addresses.emplace_back(ipv4addr);
        } else {
            auto ipv6socket = reinterpret_cast<struct sockaddr_in6*>(info->ai_addr);
            array<unsigned char, 16> bytes = {
                ipv6socket->sin6_addr.s6_addr[0],
                ipv6socket->sin6_addr.s6_addr[1],
                ipv6socket->sin6_addr.s6_addr[2],
                ipv6socket->sin6_addr.s6_addr[3],
                ipv6socket->sin6_addr.s6_addr[4],
                ipv6socket->sin6_addr.s6_addr[5],
                ipv6socket->sin6_addr.s6_addr[6],
                ipv6socket->sin6_addr.s6_addr[7],
                ipv6socket->sin6_addr.s6_addr[8],
                ipv6socket->sin6_addr.s6_addr[9],
                ipv6socket->sin6_addr.s6_addr[10],
                ipv6socket->sin6_addr.s6_addr[11],
                ipv6socket->sin6_addr.s6_addr[12],
                ipv6socket->sin6_addr.s6_addr[13],
                ipv6socket->sin6_addr.s6_addr[14],
                ipv6socket->sin6_addr.s6_addr[15]
            };
            auto ipv6addr = address_v6(bytes, ipv6socket->sin6_scope_id);
            addresses.emplace_back(ipv6addr);
        }
    }

    return addresses;
}

下一站:codereview