web-dev-qa-db-ja.com

ソケットプログラミングのINADDR_ANYを理解する

私はいくつかのソケットをプログラムしようとしているので、サーバー側ではhtonl(INADDR_ANY)を使用します。私が理解した範囲では、この関数はランダムIPを生成するように思えます(私は正しいですか?)。実際、ソケットをlocalhostにバインドしたいと思います。しかし、これを実行すると

printf("%d",htonl(INADDR_ANY));

戻り値として0を取得します。誰かが説明をすることができますか?

70
epsilones
  1. bind() of INADDR_ANYではなく「ランダムIPを生成」します。それ 利用可能なすべてのインターフェースにソケットをバインドします

  2. サーバーの場合、通常は「localhost」だけでなく、すべてのインターフェースにバインドします。

  3. ソケットをローカルホストのみにバインドする場合、構文はmy_sockaddress.sin_addr.s_addr = inet_addr("127.0.0.1");になり、bind(my_socket, (SOCKADDR *) &my_sockaddr, ...)を呼び出します。

  4. それが起こると、INADDR_ANYは「ゼロ」に等しい定数です。

    http://www.castaglia.org/proftpd/doc/devel-guide/src/include/inet.h.html

    # define INADDR_ANY ((unsigned long int) 0x00000000)
    ...
    # define INADDR_NONE    0xffffffff
    ...
    # define INPORT_ANY 0
    ...
    
  5. 慣れていない場合は、Beejのソケットプログラミングガイドを参照することをお勧めします。

    http://beej.us/guide/bgnet/

人々はまだこれを読んでいるので、追加のメモ:

man(7)ip

プロセスは、新しい着信パケットまたは接続を受信する場合、 bind(2) を使用してソケットをローカルインターフェイスアドレスにバインドする必要があります。

この場合、特定のローカル(アドレス、ポート)ペアにバインドできるIPソケットは1つだけです。バインド呼び出しでINADDR_ANYが指定されている場合、ソケットはすべてのローカルインターフェイスにバインドされます。

listen(2) が非バインドソケットで呼び出されると、ソケットはローカルアドレスがINADDR_ANYに設定されたランダムな空きポートに自動的にバインドされます。

connect(2) が非バインドソケットで呼び出されると、ソケットは自動的にランダムな空きポートまたはローカルアドレスがINADDR_ANYに設定された使用可能な共有ポートにバインドされます...

いくつかの特別なアドレスがあります:INADDR_LOOPBACK(127.0.0.1)は常にループバックデバイスを介してローカルホストを参照します。 INADDR_ANY(0.0.0.0)は、バインドするアドレスを意味します...

また:

bind()—名前をソケットにバインドする

(sin_addr.s_addr)フィールドがnetinet/in.hで定義されているように、定数INADDR_ANYに設定されている場合、呼び出し元はソケットがホスト上のすべてのネットワークインターフェイスにバインドされることを要求しています。その後、すべてのインターフェイス(バインドされた名前と一致する)からのUDPパケットとTCP接続がアプリケーションにルーティングされます。これは、サーバーが複数のネットワークにサービスを提供するときに重要になります。アドレスを指定しないままにしておくと、サーバーは、要求が到着したネットワークインターフェイスに関係なく、そのポートに対して行われたすべてのUDPパケットとTCP接続要求を受け入れることができます。

100
paulsm4

INADDR_ANYは、ソケットを特定のIPにバインドする必要がない場合に使用されます。 bind()を呼び出すときにこの値をアドレスとして使用すると、ソケットはマシンのすべてのIPへの接続を受け入れます。

57
Barmar

bindソケットとlocalhostを組み合わせて、bind関数を呼び出す前に、sockaddr_in構造体のsin_addr.s_addrフィールドを適切に設定する必要があります。適切な値は、次のいずれかの方法で取得できます。

my_sockaddress.sin_addr.s_addr = inet_addr("127.0.0.1")

または

my_sockaddress.sin_addr.s_addr=htonl(INADDR_LOOPBACK);
7
MichaelGoren

INADDR_ANYは、使用可能なすべてのインターフェースにバインドするように待機ソケットに指示します。 inet_addr("0.0.0.0")にバインドしようとするのと同じです。完全を期すために、IPv6の場合も IN6ADDR_ANY_INIT があり、IPv6ソケットの::アドレスにバインドしようとするのと同じことを説明します。

#include <netinet/in.h>

struct in6_addr addr = IN6ADDR_ANY_INIT;

また、IPv6ソケットをIN6ADDR_ANY_INITにバインドすると、ソケットはすべてのIPv6インターフェイスにバインドされ、IPv4クライアントからの接続も受け入れることができます(ただし、IPv6にマップされたアドレス)。

1
Pavel

INADDR_ANYは定数で、valueに0が含まれます。これは、ip-addを気にしないすべてのアクティブなポートから接続する場合にのみ使用されます。したがって、特定のIPを接続する場合は、my_sockaddress.sin_addr.s_addr = inet_addr( "192.168.78.2")のように言及する必要があります。

1
vivek