C 言語で getaddrinfo 関数を使用する

胡金庫 2023年10月12日
  1. C 言語で getaddrinfo 関数を使用して名前を IP アドレスにホストする
  2. C 言語で getnameinfo 関数を使用して IP アドレスをホスト名に変換する
C 言語で getaddrinfo 関数を使用する

この記事では、C 言語で getaddrinfo 関数を使用する方法に関する複数の方法を示します。

C 言語で getaddrinfo 関数を使用して名前を IP アドレスにホストする

getaddrinfo は UNIX ネットワークプログラミング機能の一部であり、ネットワークホスト情報を IP アドレスに、またはその逆に変換できます。getaddrinfo も POSIX 準拠の関数呼び出しであり、基盤となるプロトコルに関係なく変換を実行できます。

getaddrinfo は 4つの引数を取ります。

  1. 1つ目は、ホスト名または IPv4 / IPv6 形式のアドレス文字列へのポインタにすることができます。
  2. 2 番目の引数は、サービス名または 10 進整数で表されるポート番号にすることができます。
  3. 次の 2つの引数は、addrinfo 構造体へのポインターです。1つ目は、取得したソケット構造をフィルタリングするための要件を指定する hints であり、2つ目は、関数が addrinfo 構造体のリンクリストを動的に割り当てるポインタです。

hints 構造体はゼロで設定してから、そのメンバーを割り当てる必要があることに注意してください。ai_family メンバーは、アドレスファミリを示します。たとえば、IPv4 または IPv6 は、それぞれ AF_INET および AF_INET6 として示されます。この場合、サービス名の変換には関心がなく、関数の 2 番目の引数として NULL を指定します。最後に、getnameinfo を呼び出して、指定された sockaddr 構造を出力可能な形式に変換します。

#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>

int main(int argc, char const *argv[]) {
  struct addrinfo hints;
  struct addrinfo *res, *tmp;
  char host[256];

  memset(&hints, 0, sizeof(struct addrinfo));
  hints.ai_family = AF_INET;

  if (argc != 2) {
    fprintf(stderr, "%s string\n", argv[0]);
    exit(EXIT_FAILURE);
  }

  int ret = getaddrinfo(argv[1], NULL, &hints, &res);
  if (ret != 0) {
    fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(ret));
    exit(EXIT_FAILURE);
  }

  for (tmp = res; tmp != NULL; tmp = tmp->ai_next) {
    getnameinfo(tmp->ai_addr, tmp->ai_addrlen, host, sizeof(host), NULL, 0,
                NI_NUMERICHOST);
    puts(host);
  }

  freeaddrinfo(res);
  exit(EXIT_SUCCESS);
}

サンプルコマンド:

./program localhost

出力:

127.0.0.1
127.0.0.1
127.0.0.1

C 言語で getnameinfo 関数を使用して IP アドレスをホスト名に変換する

この場合、getnameinfo 関数は getaddrinfo と組み合わせて使用され、対応する IP アドレスのホスト名を取得します。最初のコマンドライン引数からのユーザー入力を処理し、それを getaddrinfo 引数として渡して、socketaddr 構造体を取得することに注意してください。最後に、各構造をホスト名文字列に変換できます。getaddrinfo は 4 番目の引数にリンクリストを格納するために動的メモリを割り当てるため、このポインタは freeaddrinfo 関数呼び出しを使用してユーザーが解放する必要があります。

#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>

int main(int argc, char const *argv[]) {
  struct addrinfo hints;
  struct addrinfo *res, *tmp;
  char host[256];

  memset(&hints, 0, sizeof(struct addrinfo));
  hints.ai_family = AF_INET;

  if (argc != 2) {
    fprintf(stderr, "%s string\n", argv[0]);
    exit(EXIT_FAILURE);
  }

  int ret = getaddrinfo(argv[1], NULL, &hints, &res);
  if (ret != 0) {
    fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(ret));
    exit(EXIT_FAILURE);
  }

  for (tmp = res; tmp != NULL; tmp = tmp->ai_next) {
    getnameinfo(tmp->ai_addr, tmp->ai_addrlen, host, sizeof(host), NULL, 0, 0);
  }

  freeaddrinfo(res);
  exit(EXIT_SUCCESS);
}

サンプルコマンド:

./program 127.0.0.1

出力:

localhost
localhost
localhost
著者: 胡金庫
胡金庫 avatar 胡金庫 avatar

DelftStack.comの創設者です。Jinku はロボティクスと自動車産業で8年以上働いています。自動テスト、リモートサーバーからのデータ収集、耐久テストからのレポート作成が必要となったとき、彼はコーディングスキルを磨きました。彼は電気/電子工学のバックグラウンドを持っていますが、組み込みエレクトロニクス、組み込みプログラミング、フロントエンド/バックエンドプログラミングへの関心を広げています。

LinkedIn Facebook

関連記事 - C Networking