2011-08-01 22 views
4

定数INADDR_ANYは、いわゆるIPv4ワイルドカードアドレスです。 ワイルドカードIPアドレスは、マルチホームホスト上のインターネットソケット をバインドするアプリケーションに役立ちます。マルチホーム ホスト上のアプリケーションがソケットをそのホストのIPアドレスの1つにバインドする場合、その ソケットはUDPデータグラムまたはTCP接続要求のみをそのIPアドレスに送信します( )。しかし、通常、マルチホームホスト のアプリケーションは、ホストのIPアドレスのいずれかを指定するデータグラムまたは接続要求 を受信できるようにし、ソケットを にバインドしてこれを可能にします。質問についてINADDR_ANY

struct sockaddr_in server_address; 
int server_sockfd = socket(AF_INET, SOCK_STREAM, 0); 
memset(&server_address, 0, sizeof(struct sockaddr_in)); 
server_address.sin_family = AF_INET; 
server_address.sin_addr.s_addr = htonl(INADDR_ANY); // here is my quesion 
server_address.sin_port = htons(9734); 

bind(server_sockfd, (struct sockaddr*)&server_address, sizeof(server_address)); 

質問>

我々は特定のIPアドレスにソケットをバインドする場合は、ソケットはそのIPアドレスに送信された送信されたUPD/TCP要求を受け取ることができます。

上記のコードで示したように、ソケットserver_sockfdはINADDR_ANYにバインドされました。 ソケットがインターネット上でリクエストを受信できれば、ここでも混乱していると思います。インターネット上のUDP/TCPのリクエストがたくさんあります。もしソケットが誰にでも返ってきたら、 はどうすれば動作するのですか?クライアント側のための

が//更新されたコード//このサーバ/クライアントプログラムの実行方法については、更新され、サーバー側のコード

int 
main(int argc, char *argv[]) 
{ 
    struct sockaddr_in6 svaddr, claddr; 
    int sfd, j; 
    ssize_t numBytes; 
    socklen_t len; 
    char buf[BUF_SIZE]; 
    char claddrStr[INET6_ADDRSTRLEN]; 

    /* Create a datagram socket bound to an address in the IPv6 somain */ 

    sfd = socket(AF_INET6, SOCK_DGRAM, 0); 
    if (sfd == -1) 
     errExit("socket"); 

    memset(&svaddr, 0, sizeof(struct sockaddr_in6)); 
    svaddr.sin6_family = AF_INET6; 
    svaddr.sin6_addr = in6addr_any;      /* Wildcard address */ 
    svaddr.sin6_port = htons(PORT_NUM); 

    if (bind(sfd, (struct sockaddr *) &svaddr, 
       sizeof(struct sockaddr_in6)) == -1) 
     errExit("bind"); 

    /* Receive messages, convert to uppercase, and return to client */ 

    for (;;) { 
     len = sizeof(struct sockaddr_in6); 
     numBytes = recvfrom(sfd, buf, BUF_SIZE, 0, 
          (struct sockaddr *) &claddr, &len); 
     if (numBytes == -1) 
      errExit("recvfrom"); 

     /* Display address of client that sent the message */ 

     if (inet_ntop(AF_INET6, &claddr.sin6_addr, claddrStr, 
        INET6_ADDRSTRLEN) == NULL) 
      printf("Couldn't convert client address to string\n"); 
     else 
      printf("Server received %ld bytes from (%s, %u)\n", 
        (long) numBytes, claddrStr, ntohs(claddr.sin6_port)); 

     for (j = 0; j < numBytes; j++) 
      buf[j] = toupper((unsigned char) buf[j]); 

     if (sendto(sfd, buf, numBytes, 0, (struct sockaddr *) &claddr, len) != 
       numBytes) 
      fatal("sendto"); 
    } 
} 

//に更新

int 
main(int argc, char *argv[]) 
{ 
    struct sockaddr_in6 svaddr; 
    int sfd, j; 
    size_t msgLen; 
    ssize_t numBytes; 
    char resp[BUF_SIZE]; 

    if (argc < 3 || strcmp(argv[1], "--help") == 0) 
     usageErr("%s host-address msg...\n", argv[0]); 

    /* Create a datagram socket; send to an address in the IPv6 somain */ 

    sfd = socket(AF_INET6, SOCK_DGRAM, 0);  /* Create client socket */ 
    if (sfd == -1) 
     errExit("socket"); 

    memset(&svaddr, 0, sizeof(struct sockaddr_in6)); 
    svaddr.sin6_family = AF_INET6; 
    svaddr.sin6_port = htons(PORT_NUM); 
    if (inet_pton(AF_INET6, argv[1], &svaddr.sin6_addr) <= 0) 
     fatal("inet_pton failed for address '%s'", argv[1]); 

    /* Send messages to server; echo responses on stdout */ 

    for (j = 2; j < argc; j++) { 
     msgLen = strlen(argv[j]); 
     if (sendto(sfd, argv[j], msgLen, 0, (struct sockaddr *) &svaddr, 
        sizeof(struct sockaddr_in6)) != msgLen) 
      fatal("sendto"); 

     numBytes = recvfrom(sfd, resp, BUF_SIZE, 0, NULL, NULL); 
     if (numBytes == -1) 
      errExit("recvfrom"); 

     printf("Response %d: %.*s\n", j - 1, (int) numBytes, resp); 
    } 

    exit(EXIT_SUCCESS); 
} 

//。

$ ./server_program & 
[1] 31047 
$ ./client_program ::1 ciao // Send to server on local host 
Server received 4 bytes from (::1, 32770) 
Response 1: CIAO 

答えて

11

それは、(a)はインターネット上のすべてのIPアドレスの要求を取得していない、それはサービスごとにIPアドレスの要求を取得します。例えば、別個のIPアドレスを有する複数のNICを有してもよく、複数のIPアドレスを管理することができる1つのNICを有してもよい(複数のNICを有することさえあり、それぞれ複数のIPアドレスを扱うことができる。見てスニペットは次のとおりです。

は...私たちは通常、 ホストのIPのいずれかを指定するデータグラムまたは接続要求を受信することができるように、マルチホームホスト上のアプリケーションをしたい(私のイタリック)を対応しています。

つまり、あなたのマシンサービス10.0.0.1510.0.0.16があるマルチホーム設定。 INADDR_ANYを使用すると、両方のアドレス()のトラフィックを受け取りません。宛のの要求を受け取ることなく、ベンチ(または惑星の他の側)のマシンとすることができます。

次の表、一番上の行は、要求先とあなたが聴いているアドレスであること、左の列であることを、あなたがリクエスト(Y)か否か(N)を与えられますかどうかを示します。

Request to> 10.0.0.15 10.0.0.16 10.0.0.17 
Bind to: *------------------------------- 
10.0.0.15 | Y   N   N 
10.0.0.16 | N   Y   N 
INADDR_ANY | Y   Y   N 

(a)のそれもは、ネット上の要求の大半は表示されません。大多数はあなたの最も近いルータ(またはおそらくあなたのISP)にそれをさえしません。 を実行してもになっていても、ローカルセグメント上の別のマシン(無差別モードにもかかわらず)に宛てられているかどうかは、特定のマシンでは見えないことがあります。

+1

@ q0987オペレーティングシステムのネットワークスタックは、何らかの種類の診断モード(「パケットスニッフィング」)が要求されない限り、そのマシンのアドレスの1つではないIPトラフィックをプログラムに配信しません。低レベルおよび/またはスイッチドネットワークでの適切なパケットアドレッシングは、間違ったアドレストラフィックの多くがネットワークスタックのIPレベルと同じくらい高くなることを防ぐでしょう。 –

+0

更新されたクライアント側のコードを参照してください。クライアント側のコードではサーバーのIPアドレスが指定されていません。10.0.0.15から10.0.0.16の範囲のIPは指定しません。次に、クライアントがクライアントから要求を送信したことをサーバーがどのように知っていますか? – q0987

+0

@ q0987ネットワーキングスタックについて学ぶのに役立ちます。ネットワーク化されたすべてのマシンは、1つ以上のIPアドレスを持つことができます。これらのIPアドレスの1つに向けられたトラフィックにのみ応答します。マジックアドレス0.0.0.0は単に "このマシンが責任を持つIPアドレスのどれか"を意味します。 –