对getaddrinfo 函数进行测试:
在Windows和Linux环境下,IPv4的地址返回与输入均保持一致。
在Windows环境下,IPv6地址返回的ai_family值为23,而在Linux下则为10。
对于输入IP为 ::和::0 的情况,这两个环境返回的IP值均被置为 ::。
Windows环境解析Linux的IPv6地址格式:fe80::20c:29ff:fed5:82f%ens33 失败,
而Linux环境解析Windows的IPv6地址格式:fe80::59d8:5d6d:25cc:42cf%14 成功。
#include
#include
#include
#ifdef WINDOWS
#include
#pragma comment(lib,"ws2_32.lib")
#endif // WINDOWS
#ifdef LINUX
#include
#include
#endif // LINUX
using namespace std;
int ParseSockAddr(const struct sockaddr* addr, string& ip, int& port)
{
void* numeric_addr = nullptr;
if (AF_INET == addr->sa_family)
{
numeric_addr = &((struct sockaddr_in*)addr)->sin_addr;
port = ntohs(((struct sockaddr_in*)addr)->sin_port);
}
else if (AF_INET6 == addr->sa_family)
{
numeric_addr = &((struct sockaddr_in6*)addr)->sin6_addr;
port = ntohs(((struct sockaddr_in6*)addr)->sin6_port);
}
else
{
return -1;
}
char addr_buff[INET6_ADDRSTRLEN];
if (inet_ntop(addr->sa_family, numeric_addr, addr_buff, sizeof(addr_buff)) == nullptr)
return -1;
ip = addr_buff;
return 0;
}
void PrintAddr(const struct addrinfo* addr)
{
printf("ai_flags:[%d], ai_family[%d], ai_socktype[%d], ai_protocol[%d], ai_addrlen[%d], ai_canonname[%s]\n",
addr->ai_flags, addr->ai_family, addr->ai_socktype, addr->ai_protocol, addr->ai_addrlen, addr->ai_canonname);
string ip;
int port = 0;
auto ret = ParseSockAddr(addr->ai_addr, ip, port);
printf("ParseSockAddr: ret[%d], Address<%s|%d>\n", ret, ip.c_str(), port);
}
int main()
{
#ifdef WINDOWS
cout << "ON WINDOWS" << endl;
WSADATA initData;
initData.wVersion = 0;
initData.wHighVersion = 2;
memset(initData.szDescription, 0, sizeof(initData.szDescription));
memset(initData.szSystemStatus, 0, sizeof(initData.szSystemStatus));
initData.iMaxSockets = 100;
initData.lpVendorInfo = nullptr;
if (WSAStartup(2, &initData) != 0)
{
std::cout << "SocketInit Failed!" << std::endl;
}
#endif
#ifdef LINUX
cout << "ON LINUX" << endl;
#endif
set ips = { "::", "::0","::1", "fe80::20c:29ff:fed5:82f","fe80::20c:29ff:fed5:82f%ens33", "fe80::59d8:5d6d:25cc:42cf%14", "0.0.0.0", "127.0.0.1","192.168.137.129" };
addrinfo hints, * res;
memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_PASSIVE;
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_IP;
auto port = "10000";
cout << endl;
for (auto& ip : ips)
{
auto ret = getaddrinfo(ip.c_str(), port, &hints, &res);
printf("getaddrinfo: ret[%d], SrcAddress:<%s|%s>\n", ret, ip.c_str(), port);
while (res != nullptr)
{
PrintAddr(res);
res = res->ai_next;
}
cout << endl;
}
cout << endl;
return 0;
}
Windows输出:
ON WINDOWS
getaddrinfo: ret[0], SrcAddress:<0.0.0.0|10000>
ai_flags:[4], ai_family[2], ai_socktype[1], ai_protocol[0], ai_addrlen[16], ai_canonname[(null)]
ParseSockAddr: ret[0], Address<0.0.0.0|10000>
getaddrinfo: ret[0], SrcAddress:<127.0.0.1|10000>
ai_flags:[4], ai_family[2], ai_socktype[1], ai_protocol[0], ai_addrlen[16], ai_canonname[(null)]
ParseSockAddr: ret[0], Address<127.0.0.1|10000>
getaddrinfo: ret[0], SrcAddress:<192.168.137.129|10000>
ai_flags:[4], ai_family[2], ai_socktype[1], ai_protocol[0], ai_addrlen[16], ai_canonname[(null)]
ParseSockAddr: ret[0], Address<192.168.137.129|10000>
getaddrinfo: ret[0], SrcAddress:<::|10000>
ai_flags:[4], ai_family[23], ai_socktype[1], ai_protocol[0], ai_addrlen[28], ai_canonname[(null)]
ParseSockAddr: ret[0], Address<::|10000>
getaddrinfo: ret[0], SrcAddress:<::0|10000>
ai_flags:[4], ai_family[23], ai_socktype[1], ai_protocol[0], ai_addrlen[28], ai_canonname[(null)]
ParseSockAddr: ret[0], Address<::|10000>
getaddrinfo: ret[0], SrcAddress:<::1|10000>
ai_flags:[4], ai_family[23], ai_socktype[1], ai_protocol[0], ai_addrlen[28], ai_canonname[(null)]
ParseSockAddr: ret[0], Address<::1|10000>
getaddrinfo: ret[0], SrcAddress:
ai_flags:[4], ai_family[23], ai_socktype[1], ai_protocol[0], ai_addrlen[28], ai_canonname[(null)]
ParseSockAddr: ret[0], Address
getaddrinfo: ret[11001], SrcAddress:
getaddrinfo: ret[0], SrcAddress:
ai_flags:[4], ai_family[23], ai_socktype[1], ai_protocol[0], ai_addrlen[28], ai_canonname[(null)]
ParseSockAddr: ret[0], Address
Linux输出:
ON LINUX
getaddrinfo: ret[0], SrcAddress:<0.0.0.0|10000>
ai_flags:[1], ai_family[2], ai_socktype[1], ai_protocol[6], ai_addrlen[16], ai_canonname[(null)]
ParseSockAddr: ret[0], Address<0.0.0.0|10000>
getaddrinfo: ret[0], SrcAddress:<127.0.0.1|10000>
ai_flags:[1], ai_family[2], ai_socktype[1], ai_protocol[6], ai_addrlen[16], ai_canonname[(null)]
ParseSockAddr: ret[0], Address<127.0.0.1|10000>
getaddrinfo: ret[0], SrcAddress:<192.168.137.129|10000>
ai_flags:[1], ai_family[2], ai_socktype[1], ai_protocol[6], ai_addrlen[16], ai_canonname[(null)]
ParseSockAddr: ret[0], Address<192.168.137.129|10000>
getaddrinfo: ret[0], SrcAddress:<::|10000>
ai_flags:[1], ai_family[10], ai_socktype[1], ai_protocol[6], ai_addrlen[28], ai_canonname[(null)]
ParseSockAddr: ret[0], Address<::|10000>
getaddrinfo: ret[0], SrcAddress:<::0|10000>
ai_flags:[1], ai_family[10], ai_socktype[1], ai_protocol[6], ai_addrlen[28], ai_canonname[(null)]
ParseSockAddr: ret[0], Address<::|10000>
getaddrinfo: ret[0], SrcAddress:<::1|10000>
ai_flags:[1], ai_family[10], ai_socktype[1], ai_protocol[6], ai_addrlen[28], ai_canonname[(null)]
ParseSockAddr: ret[0], Address<::1|10000>
getaddrinfo: ret[0], SrcAddress:
ai_flags:[1], ai_family[10], ai_socktype[1], ai_protocol[6], ai_addrlen[28], ai_canonname[(null)]
ParseSockAddr: ret[0], Address
getaddrinfo: ret[0], SrcAddress:
ai_flags:[1], ai_family[10], ai_socktype[1], ai_protocol[6], ai_addrlen[28], ai_canonname[(null)]
ParseSockAddr: ret[0], Address
getaddrinfo: ret[0], SrcAddress:
ai_flags:[1], ai_family[10], ai_socktype[1], ai_protocol[6], ai_addrlen[28], ai_canonname[(null)]
ParseSockAddr: ret[0], Address