lil*_*ood 17 c network-programming ipv4 ipv6 getaddrinfo
我试图了解getaddrinfo函数返回的内容:
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netdb.h>
int main (int argc, char *argv[])
{
struct addrinfo *res = 0 ;
getaddrinfo("localhost", NULL ,NULL,&res);
printf("ai_flags -> %i\n", res->ai_flags) ;
printf("ai_family -> %i\n", res->ai_family) ;
printf("ai_socktype -> %i\n", res->ai_socktype) ;
printf("ai_protocol -> %i\n", res->ai_protocol) ;
printf("ai_addrlen -> %i\n", res->ai_addrlen) ;
struct sockaddr_in* saddr = (struct sockaddr_in*)res->ai_addr;
printf("ai_addr hostname -> %s\n", inet_ntoa(saddr->sin_addr));
freeaddrinfo(res);
return 0 ;
}
Run Code Online (Sandbox Code Playgroud)
结果:
ai_flags -> 40
ai_family -> 2
ai_socktype -> 1
ai_protocol -> 6
ai_addrlen -> 16
ai_addr hostname -> 127.0.0.1
Run Code Online (Sandbox Code Playgroud)
在/ etc/hosts中,我有:
127.0.0.1 localhost
::1 localhost
Run Code Online (Sandbox Code Playgroud)
Getaddrinfo只返回127.0.0.1而不是:: 1?我不明白为什么?
第二个问题是我在哪里可以找到这些整数的含义(40,2,1,6等)?我读过这个男人,但那里什么都没有.
我还想知道是否可以提供IPv6地址(例如:: 1)并且该函数返回名称:localhost?
非常感谢 !!
sar*_*old 10
@jwodder和@onteria_很好地覆盖了IPv6部分,所以我只是解决数字部分:
ai_flags -> 40
Run Code Online (Sandbox Code Playgroud)
可能这将是以下两个的总和/usr/include/netdb.h:
# define AI_V4MAPPED 0x0008 /* IPv4 mapped addresses are acceptable. */
# define AI_ADDRCONFIG 0x0020 /* Use configuration of this host to choose
Run Code Online (Sandbox Code Playgroud)
这是协议族,inet,inet6,apx,unix等:
ai_family -> 2
bits/socket.h:78:#define PF_INET 2 /* IP protocol family. */
bits/socket.h:119:#define AF_INET PF_INET
Run Code Online (Sandbox Code Playgroud)
这是socket类型,流,dgram,包,rdm,seqpacket:
ai_socktype -> 1
bits/socket.h:42: SOCK_STREAM = 1, /* Sequenced, reliable, connection-based
Run Code Online (Sandbox Code Playgroud)
更高级别的协议,TCP,UDP,TCP6,UDP6,UDPlite,ospf,icmp等:
ai_protocol -> 6
Run Code Online (Sandbox Code Playgroud)
很有趣,在/etc/protocols:
tcp 6 TCP # transmission control protocol
Run Code Online (Sandbox Code Playgroud)
的大小struct sockaddr.(根据地址系列不同!呃.)
ai_addrlen -> 16
Run Code Online (Sandbox Code Playgroud)
这是因为你要回来了struct sockaddr_in,看看linux/in.h:
#define __SOCK_SIZE__ 16 /* sizeof(struct sockaddr) */
struct sockaddr_in {
sa_family_t sin_family; /* Address family */
__be16 sin_port; /* Port number */
struct in_addr sin_addr; /* Internet address */
/* Pad to size of `struct sockaddr'. */
unsigned char __pad[__SOCK_SIZE__ - sizeof(short int) -
sizeof(unsigned short int) - sizeof(struct in_addr)];
};
Run Code Online (Sandbox Code Playgroud)
最后一个,来自/etc/hosts:)
ai_addr hostname -> 127.0.0.1
Run Code Online (Sandbox Code Playgroud)
res还包含一个字段struct addrinfo *ai_next;,它是指向找到的其他条目的指针getaddrinfo,如果没有其他条目,则为NULL.如果您检查res->ai_next,您应该找到IPv6条目.
对于a中的整数字段struct addrinfo,它们对应于具有实现定义值的预定义常量,并且整数值本身不是普遍感兴趣的.如果你想知道一个给定的字段表示,比较其对可分配给该字段的常数(SOCK_STREAM,SOCK_DGRAM,等了ai_socktype; IPPROTO_TCP,IPPROTO_UDP等了ai_protocol;等等),或者为ai_flags,测试对应于每个位预定义常量(例如if (res->ai_flags & AI_NUMERICHOST) {printf("ai_flags has AI_NUMERICHOST\n"); }).
extern struct sockaddr_in6 create_socket6(int port, const char * address) {
struct addrinfo hints, *res, *resalloc;
struct sockaddr_in6 input_socket6;
int errcode;
/* 0 out our structs to be on the safe side */
memset (&hints, 0, sizeof (hints));
memset (&input_socket6, 0, sizeof(struct sockaddr_in6));
/* We only care about IPV6 results */
hints.ai_family = AF_INET6;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_DEFAULT;
errcode = getaddrinfo (address, NULL, &hints, &res);
if (errcode != 0)
{
perror ("[ERROR] getaddrinfo ");
return input_socket6;
}
resalloc = res;
while (res)
{
/* Check to make sure we have a valid AF_INET6 address */
if(res->ai_family == AF_INET6) {
/* Use memcpy since we're going to free the res variable later */
memcpy (&input_socket6, res->ai_addr, res->ai_addrlen);
/* Here we convert the port to network byte order */
input_socket6.sin6_port = htons (port);
input_socket6.sin6_family = AF_INET6;
break;
}
res = res->ai_next;
}
freeaddrinfo(resalloc);
return input_socket6;
}
Run Code Online (Sandbox Code Playgroud)
这是一些解释它的代码.基本上除非你给getaddrinfo一些提示告诉它只能使用IPV6,它也会给出IPV4结果.这就是为什么你必须如图所示循环结果.
| 归档时间: |
|
| 查看次数: |
22400 次 |
| 最近记录: |