要同时获取 IPv4 和 IPv6 地址,可以使用 POSIX 标准中的 getaddrinfo()
函数。这个函数能够返回一个链表结构,其中包含主机的所有地址信息。我们可以遍历这个链表,分别获取 IPv4 和 IPv6 地址。下面是一个示例代码:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
int main() {
struct addrinfo *result, *rp;
int s;
s = getaddrinfo(NULL, "0", NULL, &result);
if (s != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));
exit(EXIT_FAILURE);
}
for (rp = result; rp != NULL; rp = rp->ai_next) {
if (rp->ai_family == AF_INET) {
printf("IPv4 address: %s\n", inet_ntoa(((struct sockaddr_in *)rp->ai_addr)->sin_addr));
} else if (rp->ai_family == AF_INET6) {
char ipv6[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, &((struct sockaddr_in6 *)rp->ai_addr)->sin6_addr, ipv6, INET6_ADDRSTRLEN);
printf("IPv6 address: %s\n", ipv6);
}
}
freeaddrinfo(result);
return 0;
}
在不同的操作系统上获取本地 IP 地址的代码也会略有不同。在 Windows 系统上,可以使用 GetAdaptersInfo()
函数来获取网卡信息。而在 Unix/Linux 系统上,可以使用 getifaddrs()
函数来获取网卡信息。下面是一个跨平台的示例代码:
#ifdef _WIN32
#include <winsock2.h>
#include <iphlpapi.h>
#pragma comment(lib, "iphlpapi.lib")
#else
#include <sys/types.h>
#include <ifaddrs.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#endif
void get_local_ip(char *ip, int size) {
#ifdef _WIN32
IP_ADAPTER_INFO *pAdapterInfo;
ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO);
pAdapterInfo = (IP_ADAPTER_INFO *)malloc(sizeof(IP_ADAPTER_INFO));
if (GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW) {
free(pAdapterInfo);
pAdapterInfo = (IP_ADAPTER_INFO *)malloc(ulOutBufLen);
GetAdaptersInfo(pAdapterInfo, &ulOutBufLen);
}
strcpy_s(ip, size, pAdapterInfo->IpAddressList.IpAddress.String);
free(pAdapterInfo);
#else
struct ifaddrs *ifaddr, *ifa;
int family, s;
char host[NI_MAXHOST];
if (getifaddrs(&ifaddr) == -1) {
perror("getifaddrs");
return;
}
for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
if (ifa->ifa_addr == NULL)
continue;
family = ifa->ifa_addr->sa_family;
if (family == AF_INET) {
s = getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in), host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
if (s != 0) {
printf("getnameinfo() failed: %s\n", gai_strerror(s));
return;
}
strcpy(ip, host);
break;
}
}
freeifaddrs(ifaddr);
#endif
}
使用 C 语言获取 IPv4 和 IPv6 地址以及本地 IP 地址的代码在不同操作系统上会有一些差异。但通过使用跨平台的函数和库,我们可以编写出可以在多个平台上运行的程序。