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 ;
}
結果 :
ai_flags -> 40
ai_family -> 2
ai_socktype -> 1
ai_protocol -> 6
ai_addrlen -> 16
ai_addr hostname -> 127.0.0.1
/ etc/hostsには、次のものがあります。
127.0.0.1 localhost
::1 localhost
Getaddrinfoは127.0.0.1のみを返し、:: 1は返しませんか?理由がわかりませんか?
2番目の質問は、これらのint(40、2、1、6など)の意味をどこで見つけることができるかです。私はその男を読みましたが、それについては何もありません。
また、IPv6アドレス(たとえば:: 1)を指定でき、関数が名前を返すかどうかも知りたいと思いました:localhost?
どうもありがとう !!
@jwodderと@onteria_はIPv6の部分をうまくカバーしているので、numbersの部分に取り組むだけです。
ai_flags -> 40
おそらく、これは/usr/include/netdb.h
の次の2つの合計になります。
# define AI_V4MAPPED 0x0008 /* IPv4 mapped addresses are acceptable. */
# define AI_ADDRCONFIG 0x0020 /* Use configuration of this Host to choose
これはプロトコルファミリ、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
これはソケットタイプ、ストリーム、dgram、パケット、rdm、seqpacketです:
ai_socktype -> 1
bits/socket.h:42: SOCK_STREAM = 1, /* Sequenced, reliable, connection-based
上位レベルプロトコル、TCP、UDP、TCP6、UDP6、UDPlite、ospf、icmpなど:
ai_protocol -> 6
おかしなことに、/etc/protocols
:
tcp 6 TCP # transmission control protocol
struct sockaddr
のサイズ。 (アドレスファミリによって異なります!うーん。)
ai_addrlen -> 16
これは、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)];
};
そして最後のもの、/etc/hosts
から:)
ai_addr hostname -> 127.0.0.1
res
には、フィールド_struct addrinfo *ai_next;
_も含まれています。これは、getaddrinfo
によって検出された追加のエントリへのポインタであり、他のエントリがなかった場合はNULLです。 _res->ai_next
_を調べると、IPv6エントリが見つかるはずです。
_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;
}
これはそれを説明するいくつかのコードです。基本的に、getaddrinfoにIPV6でのみ機能するように指示するヒントを与えない限り、IPV4の結果も得られます。そのため、示されているように結果をループする必要があります。
他の答えはほとんどの部分に与えられました、しかしこの最後の部分に答えるために:
また、IPv6アドレス(たとえば:: 1)を指定でき、関数が名前を返すかどうかも知りたいと思いました:localhost?
必要な関数はgetnameinfo()
です。ソケットアドレスを指定すると、文字列名が返されます。