我仍在学习套接字,并且不清楚为什么它不能打印出127.0.0.1。即使我将localhost替换为127.0.0.1,我也会收到其他一些IP,我猜这是我的路由器或其他东西。我一直以为这应该返回127.0.0.1。这是我收到的输出:
hostname: 28.30.0.0
hostname: 28.30.0.0
hostname: 28.30.0.0
hostname: 28.30.0.0
hostname: 16.2.0.0
hostname: 16.2.0.0
Run Code Online (Sandbox Code Playgroud)
这是基本代码:
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
int main()
{
struct addrinfo* feed_server = NULL;
getaddrinfo("localhost", NULL, NULL, &feed_server);
struct addrinfo *res;
for(res = feed_server; res != NULL; res = res->ai_next)
{
printf("hostname: %s\n", inet_ntoa(*((struct in_addr*)(res->ai_addr))));
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
res->ai_addr
是类型的struct sockaddr*
,不是struct in_addr*
。
您需要执行以下操作:
for(res = feed_server; res != NULL; res = res->ai_next)
{
/* ideally look at the sa_family here to make sure it is AF_INET before casting */
struct sockaddr_in* saddr = (struct sockaddr_in*)res->ai_addr;
printf("hostname: %s\n", inet_ntoa(saddr->sin_addr));
}
Run Code Online (Sandbox Code Playgroud)
原代码有两个问题:
我通常至少在 Linux 系统上看到的一件事是 localhost 的 getaddrinfo 通常首先返回 IPv6 ::1 地址。
从打印的地址我可以知道您正在运行一个在结构中包含 sockaddrs 长度的操作系统。例如 OS X 上 struct sockaddr 的定义是:
struct sockaddr {
__uint8_t sa_len; /* total length */
sa_family_t sa_family; /* [XSI] address family */
char sa_data[14]; /* [XSI] addr value (actually larger) */
};
Run Code Online (Sandbox Code Playgroud)
对于 struct sockaddr_in 和 sockaddr_in6 来说,sa_family 之后的下一个成员是端口,它始终是两个字节。因此,当您将这些结构中的任何一个转换为结构 in_addr 时,您将得到一个地址 sa_len.sa_family.0.0 (假设您没有提供 getaddrinfo 的端口 - 如果您提供端口,则 0.0 将被替换为端口字节值)。
所以 gettaddr info 返回两个 IPv6 地址:28.30.0.0 - sizeof struct sockaddr_in6 = 28 和 af_family = 30
和两个 IPv4 地址:16.2.0.0 - sizeof struct sockaddr_in = 16 和 af_family = 2
要正确执行此操作,您可以按照其他答案所说的操作并使用 getnameinfo。然而,使用 inet_ntop (不是 inet_ntoa)也同样好。
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h> /* for memset */
int main()
{
char addr_buf[64];
struct addrinfo* feed_server = NULL;
memset(addr_buf, 0, sizeof(addr_buf));
getaddrinfo("localhost", NULL, NULL, &feed_server);
struct addrinfo *res;
for(res = feed_server; res != NULL; res = res->ai_next)
{
if ( res->ai_family == AF_INET )
{
inet_ntop(AF_INET, &((struct sockaddr_in *)res->ai_addr)->sin_addr, addr_buf, sizeof(addr_buf));
}
else
{
inet_ntop(AF_INET6, &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, addr_buf, sizeof(addr_buf));
}
printf("hostname: %s\n", addr_buf);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
````