You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将struct sockaddr_in6*转换为boost::asio::ip::address_v6

修正方案

你原有代码的问题主要有四点:

  1. IPv6转换逻辑直接用reinterpret_cast转换std::array值类型属于非法操作,同时使用了__in6_u这类平台私有内部成员,兼容性差
  2. 没有明确判断地址族为AF_INET6就进入IPv6处理逻辑,可能引入其他地址族的脏数据
  3. 漏了getaddrinfo返回结构体的内存释放逻辑,会产生内存泄漏
  4. IPv4部分的htonl语义错误,虽然小端设备上运行效果和正确的ntohl一致,但在大端设备上会出错

完整修正代码

#include <iostream>
using std::cout;

#include <netdb.h>
#include <cstring>
#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);
            // 修正语义:网络字节序转主机字节序用ntohl
            auto ipv4addr = address_v4(ntohl(ipv4socket->sin_addr.s_addr));
            addresses.emplace_back(ipv4addr);
        }
        else if (info->ai_family == AF_INET6) {
            auto ipv6socket = reinterpret_cast<struct sockaddr_in6*>(info->ai_addr);
            // 用标准公开成员s6_addr获取16字节IPv6地址,构造asio要求的bytes_type
            address_v6::bytes_type addr_bytes;
            std::memcpy(addr_bytes.data(), ipv6socket->sin6_addr.s6_addr, addr_bytes.size());
            auto ipv6addr = address_v6(addr_bytes, ipv6socket->sin6_scope_id);
            addresses.emplace_back(ipv6addr);
        }
    }
    // 释放getaddrinfo申请的堆内存
    freeaddrinfo(pai);
    return addresses;
}

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

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

    return 0;
}

关键修改说明

  • 新增明确的AF_INET6地址族判断,避免处理其他非IPv6的地址族数据
  • 改用POSIX标准规定的公开成员s6_addr获取IPv6原始地址,避免使用平台私有成员,提升兼容性
  • 通过memcpy拷贝16字节地址数据构造address_v6要求的bytes_type对象,规避非法类型转换和严格别名规则问题
  • 补充freeaddrinfo调用释放系统分配的地址信息内存,避免内存泄漏
  • 修正IPv4部分的字节序转换函数为ntohl,语义更准确,兼容大端架构设备

内容的提问来源于stack exchange,提问作者user3515670

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.20 10:06:04