10

Beej の Simple Clientサンプル コードは、最初の IP アドレスに接続できるまで、getaddrinfo() から返されたすべての IP アドレスを繰り返します。以下のコードを参照してください。

これは常に必要ですか、それとも getaddrinfo() によって返された最初のアドレスへの接続を試みるだけでよいと仮定してもよろしいですか?

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

if ((rv = getaddrinfo(argv[1], PORT, &hints, &servinfo)) != 0) {
    fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
    return 1;
}

// ------------------------------------------------------------
// loop through all the results and connect to the first we can
for(p = servinfo; p != NULL; p = p->ai_next) {
    if ((sockfd = socket(p->ai_family, p->ai_socktype,
            p->ai_protocol)) == -1) {
        perror("client: socket");
        continue;
    }

    if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
        close(sockfd);
        perror("client: connect");
        continue;
    }

    break;
}
4

5 に答える 5

10

はい、すべてのアドレスを反復処理する必要があります。特に、宛先ホストで IPv6 アドレスが有効になっているが、ローカル ホストでは有効になっていない場合を考えてみてください。 は家族の住所getaddrinfo()を返しますが、またはの呼び出しは失敗します。AF_INET6socket()connect()

また、ホストが実装する複数のプロトコル (たとえば、TCP に加えて SCTP) をサポートし、宛先ホストがサポートしていない可能性もあります。ヒント構造体SOCK_STREAMのメンバーを設定していないため、ソケットをサポートするすべてのプロトコルを表すアドレスが返されます。ai_protocolSOCK_STREAM

于 2012-07-20T06:14:16.753 に答える
4

上記の他の回答に加えて、大規模な Web サイトなどでは、冗長性のために複数の A レコードが公開される可能性があるという一般的なケースを考慮してください。最初のアドレスへの送信が失敗した場合はconnect()、他のアドレスも試してください。

于 2012-07-20T12:31:23.343 に答える
2

接続先のサーバー ホストには複数のアドレスが関連付けられている場合がありますが、実際のサーバー プログラムはそれらのアドレスの 1 つだけをリッスンします。サーバープログラムがリッスンしている正確なアドレスをクライアントが知らない場合は、正しいアドレスを見つけて接続できるまで、ホストが持っているすべてのアドレスを試す必要があります。

于 2012-07-20T05:54:06.237 に答える
1

はい、それらすべてをループする必要があります。最初のアドレス (または選択したアドレス) が実際に有効であるという保証はありません。そのため、チュートリアルではそのようにしています。

于 2012-07-20T06:16:34.993 に答える
0

この時点で、ソケットを初めて使用すると仮定します。はい、getaddrinfo を使用した後、さらに検証するためにアドレス情報を取得できるため、これは非常に重要です。

于 2012-07-20T04:27:51.633 に答える