如何将struct sockaddr_in6*转换为boost::asio::ip::address_v6
修正方案
你原有代码的问题主要有四点:
- IPv6转换逻辑直接用
reinterpret_cast转换std::array值类型属于非法操作,同时使用了__in6_u这类平台私有内部成员,兼容性差 - 没有明确判断地址族为
AF_INET6就进入IPv6处理逻辑,可能引入其他地址族的脏数据 - 漏了
getaddrinfo返回结构体的内存释放逻辑,会产生内存泄漏 - 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
相关产品推荐
相关产品推荐

