我还在学习套接字并且不清楚为什么这不会打印出127.0.0.1。即使我用127.0.0.1替换localhost这个词,我也会收到一些其他的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
以下是基本代码:
#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;
}
答案 0 :(得分:4)
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));
}
答案 1 :(得分:3)
您应该使用提示来调用getaddrinfo
。因为要解析“localhost”或任何/etc/hosts
记录hints.af_family
必须设置为AF_INET
。
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
int main()
{
struct addrinfo hints;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_INET;
getaddrinfo("localhost", NULL, &hints, &feed_server);
struct addrinfo *res;
for(res = feed_server; res != NULL; res = res->ai_next){
struct sockaddr_in* saddr = (struct sockaddr_in*)res->ai_addr;
printf("hostname: %s\n", inet_ntoa(saddr->sin_addr))
}
return 0;
}
答案 2 :(得分:1)
原始代码存在两个问题:
我通常至少在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) */
};
对于struct sockaddr_in和sockaddr_in6,sa_family之后的下一个成员是总是两个字节的端口。因此,当您将这些结构中的任何一个转换为结构in_addr时,您将获得一个sa_len.sa_family.0.0的地址(假设您没有为getaddrinfo提供端口 - 如果您提供端口,则0.0将替换为ports字节值)。
因此gettaddr信息会返回两个IPv6地址: 28.30.0.0 - sizeof struct sockaddr_in6 = 28 and 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;
}
```