getaddrinfo(getaddrinfoを使ってsockaddrを作成する)

最初の例は、gethostbynameを使い慣れている人を意識したものにしてみましたが、次は、それとはちょっと違った使い方の紹介です。 socketはAF_INETやAF_INET6などのプロトコルファミリとソケットの種類を指定する必要があります。 また、connectシステムコールには、sockaddr構造体を引数として渡す必要があります。 この例では、getaddrinfoによって得られる結果をこれらのシステムコールに渡すための情報としてそのまま使ってしまいます。

サンプルコード


#include <winsock2.h>
#include <ws2tcpip.h>

int
main()
{
 char *hostname = "localhost";
 char *service = "80";
 struct addrinfo hints, *res;
 int err;
 SOCKET sock;

 WSADATA data;
 WSAStartup(MAKEWORD(2,0), &data);

 memset(&hints, 0, sizeof(hints));
 hints.ai_socktype = SOCK_STREAM;
 hints.ai_family = AF_INET;

 if ((err = getaddrinfo(hostname, service, &hints, &res)) != 0) {
   printf("error %d\n", err);
   return 1;
 }

 sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
 if (sock == INVALID_SOCKET) {
   printf("socket\n");
   return 1;
 }

 if (!connect(sock, res->ai_addr, res->ai_addrlen)) {
   printf("error connect\n");
   return 1;
 }

 freeaddrinfo(res);

 WSACleanup();

 return 0;
}

getaddrinfoの2つ目の引数はポート番号かサービス名です。 例えば、上記例でservice="80"になっているところをservice="http"にしても同様の結果が得られます。

上記例では、IPv4での名前解決を行なっていますが、hints.ai_family = AF_INET6にするとIPv6での名前解決になります。 IPv4とIPv6両方で行なう場合には、hints.ai_family = PF_UNSPECにします。

IPv6基礎検定

YouTubeチャンネルやってます!