在Linux系统上用C++将主机名称转换为IPv4、IPv6地址
功能
指定一个std::string类型的主机名称,函数解析主机名称为IP地址,含IPv4和IPv6,解析结果以std::vector<std::string>类型返回。解析出错或者解析失败抛出std::string类型的异常消息。
源代码
以前随便写的一个解析域名为IP地址的功能现在需要支持IPv6,所以做了些调整。最后结果如下:
/*
C++,将域名解析为IP地址(含IPv4和IPv6)
编译: g++ -o main main.cpp
执行:./main
效果:
$ ./main
13.226.120.15
13.226.120.23
13.226.120.56
13.226.120.3
2600:9000:21e1:1200:1c:b3b0:7700:93a1
2600:9000:21e1:bc00:1c:b3b0:7700:93a1
2600:9000:21e1:9a00:1c:b3b0:7700:93a1
2600:9000:21e1:4e00:1c:b3b0:7700:93a1
2600:9000:21e1:a200:1c:b3b0:7700:93a1
2600:9000:21e1:3600:1c:b3b0:7700:93a1
2600:9000:21e1:1a00:1c:b3b0:7700:93a1
2600:9000:21e1:1800:1c:b3b0:7700:93a1
*/
// getaddrinfo, gai_strerror, freeaddrinfo
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
// inet_ntop
#include <arpa/inet.h>
// strerror
#include <cstring>
#include <string>
#include <vector>
#include <iostream>
// 域名解析为IP地址,返回地址列表。
std::vector<std::string> hostToIPs(const std::string& host) {
std::vector<std::string> addressList;
addrinfo hints;
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = 0;
hints.ai_flags = 0;
hints.ai_canonname = nullptr;
hints.ai_addr = nullptr;
hints.ai_next = nullptr;
addrinfo* result = nullptr;
auto res = getaddrinfo(host.c_str(), nullptr, &hints, &result);
if (0 != res) {
throw std::string(gai_strerror(res));
}
if (nullptr != result) {
int bufferSize = 64;
char buffer[64];
void* pointer;
for (auto rp = result; rp != nullptr; rp = rp->ai_next) {
switch (rp->ai_family) {
case AF_INET:
pointer = (void*)&(((sockaddr_in*)(rp->ai_addr))->sin_addr);
break;
case AF_INET6:
pointer = (void*)&(((sockaddr_in6*)(rp->ai_addr))->sin6_addr);
break;
default:
continue;
}
if (nullptr == inet_ntop(rp->ai_family, pointer, buffer, bufferSize)) {
freeaddrinfo(result);
throw std::string("Run inet_ntop fail, errno is ") + std::to_string(errno)
+ ", message: " + std::string(strerror(errno));
}
addressList.emplace_back(std::string(buffer));
}
freeaddrinfo(result);
}
if (addressList.size() <= 0) {
throw std::string("address list is empty");
}
return addressList;
}
int main() {
try {
for (const auto& address : hostToIPs("www.english.com")) {
std::cout << address << std::endl;
}
} catch (const std::string& e) {
std::cout << e << std::endl;
}
return 0;
}
运行截图
程序在Ubuntu上开发调试,结果是OK的。解析结果支持IPv4和IPv6地址,主要参考材料是man手册。运行截图: