79

複数のネットワークインターフェイスを持つホスト間でマルチキャストUDPを使用しています。私はboost::asioを使用していますが、レシーバーが行う必要のある2つの操作(bind、join-group)に混乱しています。

参加するすべてのマルチキャストグループで指定するときに、バインド中にインターフェイスのローカルアドレスを指定する必要があるのはなぜですか。

姉妹質問はマルチキャストポートに関するものです。送信中にマルチキャストアドレスとポートに送信するので、マルチキャストグループへのサブスクリプション中に、ポートではなくアドレスのみを指定するのはなぜですか。練る。

注:「join-group」はラッパーsetsockopt(IP_ADD_MEMBERSHIP)であり、文書化されているように、同じソケットで複数回呼び出されて、異なるグループにサブスクライブできます(異なるネットワークを介して?)。したがって、グループにサブスクライブするたびに、バインド呼び出しを破棄してポートを指定することは完全に理にかなっています。

私が見たところ、常に「0.0.0.0」にバインドし、グループに参加するときにインターフェイスアドレスを指定すると、非常にうまく機能します。混乱している。

4

4 に答える 4

67

マルチキャストの受信時にUDPソケットをバインドするということは、データを受信するアドレスとポートを指定することを意味します(TCPアクセプターバインドの場合のようにローカルインターフェイスではありません)。この場合に指定されたアドレスにはフィルタリングの役割があります。つまり、ソケットは、その後どのグループがソケットによって参加されても、そのマルチキャストアドレスとポートに送信されたデータグラムのみを受信します。これは、INADDR_ANY(0.0.0.0)にバインドすると、マルチキャストグループに送信されたデータグラムを受信したのに対し、ローカルインターフェイスにバインドすると、そのインターフェイスが送信されたネットワークでデータグラムが送信されていても、何も受信しなかった理由を説明しています。対応しました。

UNIX®ネットワークプログラミング第1巻、第3版からの引用:WRスティーブンスによるSocketsNetworkingAPI。21.10。送受信

[...]受信ソケットにマルチキャストグループとポート、たとえば239.255.1.2ポート8888をバインドする必要があります(ワイルドカードIPアドレスとポート8888をバインドすることもできますが、マルチキャストアドレスをバインドすると、ソケットが受信できなくなります。ポート8888宛てに到着する可能性のあるその他のデータグラム。)次に、受信ソケットをマルチキャストグループに参加させます。送信ソケットは、この同じマルチキャストアドレスとポート(たとえば、239.255.1.2ポート8888)にデータグラムを送信します。

于 2012-05-24T14:25:24.560 に答える
57

「バインド」操作とは、基本的に「このローカルUDPポートをデータの送受信に使用することです。つまり、そのUDPポートをアプリケーション専用に割り当てます(TCPソケットについても同様です)。

「0.0.0.0」(INADDR_ANY)にバインドすると、基本的にTCP / IP層に、使用可能なすべてのアダプターをリッスンに使用し、送信に最適なアダプターを選択するように指示します。これは、ほとんどのソケットコードの標準的な方法です。IPアドレスに0を指定しないのは、特定のネットワークアダプターで送受信する場合のみです。

同様に、バインド中にポート値0を指定すると、OSはそのソケットにランダムに使用可能なポート番号を割り当てます。したがって、UDPマルチキャストの場合、マルチキャストトラフィックの送信先となる特定のポート番号でINADDR_ANYにバインドします。

「マルチキャストグループに参加」操作(IP_ADD_MEMBERSHIP)が必要なのは、基本的に、宛先MACアドレスが自分のイーサネットフレームをリッスンするようにネットワークアダプターに指示するだけでなく、IPマルチキャストトラフィックをリッスンするようにイーサネットアダプター( NIC )に指示するためです。対応するマルチキャストイーサネットアドレスにも適しています。各マルチキャストIPは、マルチキャストイーサネットアドレスにマップされます。ソケットを使用して特定のマルチキャストIPに送信する場合、イーサネットフレームの宛先MACアドレスは、マルチキャストIPに対応するマルチキャストMACアドレスに設定されます。マルチキャストグループに参加すると、(自身のアドレスに加えて)同じMACアドレスに送信されたトラフィックをリッスンするようにNICを構成します。

ハードウェアのサポートがなければ、マルチキャストはプレーンブロードキャストIPメッセージよりも効率的ではありません。参加操作は、ルーター/ゲートウェイに他のネットワークからのマルチキャストトラフィックを転送するようにも指示します。(MBONEを覚えている人はいますか?)

マルチキャストグループに参加すると、そのIPアドレスのすべてのポートのすべてのマルチキャストトラフィックがNICによって受信されます。バインドされたリスニングポート宛てのトラフィックのみが、TCP/IPスタックを介してアプリに渡されます。マルチキャストサブスクリプション中にポートが指定される理由に関しては、マルチキャストIPがまさにそれであるためです。IPのみです。「ポート」は、上位プロトコル(UDPおよびTCP)のプロパティです。

マルチキャストIPアドレスがさまざまなサイトのマルチキャストイーサネットアドレスにどのようにマッピングされるかについて詳しく読むことができます。 ウィキペディアの記事はそれが得るのとほぼ同じくらい良いです:

IANAはOUIMACアドレス01:00:5eを所有しているため、マルチキャストパケットはイーサネットMACアドレス範囲01:00:5e:00:00:00-01:00:5e:7f:ff:ffを使用して配信されます。これは、23ビットの使用可能なアドレス空間です。最初のオクテット(01)には、ブロードキャスト/マルチキャストビットが含まれます。28ビットマルチキャストIPアドレスの下位23ビットは、使用可能なイーサネットアドレス空間の23ビットにマッピングされます。

于 2012-05-22T04:00:10.563 に答える
11

マルチキャスト( udp )ソケットをバインドするとはどういう意味ですか?次の引用で部分的に真実である限り:

「バインド」操作とは、基本的に「このローカルUDPポートをデータの送受信に使用することです。つまり、そのUDPポートをアプリケーション専用に割り当てます。

例外が1つあります。オプションが適用されている場合、複数のアプリケーションがリスニング用に同じポートを共有できます(通常はマルチキャストデータグラムに実用的な価値があります)SO_REUSEADDR。例えば

int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); // create UDP socket somehow
...
int set_option_on = 1;
// it is important to do "reuse address" before bind, not after
int res = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*) &set_option_on, 
    sizeof(set_option_on));
res = bind(sock, src_addr, len);

複数のプロセスがそのような「再利用バインディング」を実行した場合、その共有ポートで受信されたすべてのUDPデータグラムが各プロセスに配信されます(マルチキャストトラフィックとの自然な結合を提供します)。

いくつかのケースで何が起こるかについての詳細は次のとおりです。

  1. 解放ポートへのバインド(「排他的」または「再利用」)の試行は成功します

  2. ポートがすでに「再利用バインド」されている場合、「排他的バインド」の試行は失敗します

  3. 一部のプロセスが「排他的バインディング」を維持している場合、「バインディングの再利用」の試みは失敗します

于 2013-01-30T20:57:10.630 に答える
7

SENDINGマルチキャストソケットとRECEIVINGマルチキャストソケットを区別することも非常に重要です。

RECEIVINGマルチキャストソケットに関する上記のすべての回答に同意します。OPは、RECEIVINGソケットをインターフェイスにバインドしても効果がないことを指摘しました。ただし、マルチキャストSENDINGソケットをインターフェイスにバインドする必要があります。

マルチホームサーバー上のSENDINGマルチキャストソケットの場合、送信先のインターフェイスごとに個別のソケットを作成することが非常に重要です。バインドされたSENDINGソケットは、インターフェイスごとに作成する必要があります。

  // This is a fix for that bug that causes Servers to pop offline/online.
  // Servers will intermittently pop offline/online for 10 seconds or so.
  // The bug only happens if the machine had a DHCP gateway, and the gateway is no longer accessible.
  // After several minutes, the route to the DHCP gateway may timeout, at which
  // point the pingponging stops.
  // You need 3 machines, Client machine, server A, and server B
  // Client has both ethernets connected, and both ethernets receiving CITP pings (machine A pinging to en0, machine B pinging to en1)
  // Now turn off the ping from machine B (en1), but leave the network connected.
  // You will notice that the machine transmitting on the interface with
  // the DHCP gateway will fail sendto() with errno 'No route to host'
  if ( theErr == 0 )
  {
     // inspired by 'ping -b' option in man page:      
     //      -b boundif
     //             Bind the socket to interface boundif for sending.
     struct sockaddr_in bindInterfaceAddr;
     bzero(&bindInterfaceAddr, sizeof(bindInterfaceAddr));
     bindInterfaceAddr.sin_len = sizeof(bindInterfaceAddr);
     bindInterfaceAddr.sin_family = AF_INET;
     bindInterfaceAddr.sin_addr.s_addr = htonl(interfaceipaddr);
     bindInterfaceAddr.sin_port = 0; // Allow the kernel to choose a random port number by passing in 0 for the port.
     theErr = bind(mSendSocketID, (struct sockaddr *)&bindInterfaceAddr, sizeof(bindInterfaceAddr));
     struct sockaddr_in serverAddress;
     int namelen = sizeof(serverAddress);  
     if (getsockname(mSendSocketID, (struct sockaddr *)&serverAddress, (socklen_t *)&namelen) < 0) {
        DLogErr(@"ERROR Publishing service... getsockname err");
     }
     else
     {
        DLog( @"socket %d bind, %@ port %d", mSendSocketID, [NSString stringFromIPAddress:htonl(serverAddress.sin_addr.s_addr)], htons(serverAddress.sin_port) );
     }

この修正がないと、マルチキャスト送信は断続的にsendto()errno'ホストへのルートがありません'を取得します。DHCPゲートウェイのプラグを抜くと、Mac OS XマルチキャストSENDINGソケットが混乱する理由を誰かが明らかにできるなら、私はそれを聞きたいです。

于 2015-04-08T23:08:40.807 に答える