4

以下の MulticastReceiver の実装にバグがあるようです。

<224.0.25.46,13001> と <224.0.25.172,13001> の 2 つのインスタンスを作成すると、各ストリームで各パケットが 2 回取得されます。ポインタはありますか?私の推測は REUSEADDR ですか?

class MulticastReceiverSocket {
  protected:
    const std::string listen_ip_;
    const int listen_port_;
    int socket_file_descriptor_;
  public:

  MulticastReceiverSocket ( const std::string & listen_ip, 
                            const int listen_port )
    : listen_ip_ ( listen_ip ), listen_port_ ( listen_port ), 
      socket_file_descriptor_ ( -1 )
  { 

  /* create socket to join multicast group on */
  socket_file_descriptor_ = socket ( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
  if ( socket_file_descriptor_ < 0 ) 
    { exit(1); }

  /* set reuse port to on to allow multiple binds per host */
  {
    int flag_on = 1;
    if ( ( setsockopt ( socket_file_descriptor_, SOL_SOCKET, 
                        SO_REUSEADDR, &flag_on,
                        sizeof(flag_on) ) ) < 0 ) 
      { exit(1); }
  }

  McastJoin ( );

  {
    /* construct a multicast address structure */
    struct sockaddr_in mcast_Addr;
    bzero ( &mcast_Addr, sizeof(mcast_Addr) );
    mcast_Addr.sin_family = AF_INET;
    mcast_Addr.sin_addr.s_addr = htonl(INADDR_ANY);
    mcast_Addr.sin_port = htons ( listen_port_ );

    /* bind to specified port onany interface */
    if ( bind ( socket_file_descriptor_, (struct sockaddr *) &mcast_Addr, sizeof ( struct sockaddr_in ) ) < 0 ) 
       { exit(1); } 
  }
}

void McastJoin ( )
{ 
    /* construct an IGMP join request structure */

    struct ip_mreq mc_req;
    inet_pton ( AF_INET, listen_ip_.c_str(), &(mc_req.imr_multiaddr.s_addr) ); 
    mc_req.imr_interface.s_addr = htonl(INADDR_ANY);

    /* send an ADD MEMBERSHIP message via setsockopt */
    if ( ( setsockopt ( socket_file_descriptor_, IPPROTO_IP, IP_ADD_MEMBERSHIP, 
                (void*) &mc_req, sizeof(mc_req))) < 0) 
    {
      printf ("setsockopt() failed in IP_ADD_MEMBERSHIP %s\n", listen_ip_.c_str() );
      exit(1);
    } 

}

inline int ReadN ( const unsigned int _len_, void * _dest_ ) 
{
  if ( socket_file_descriptor_ != -1 )
    {
      return recvfrom ( socket_file_descriptor_, _dest_, _len_, 0, NULL, NULL );
    }
  return -1;
}

アドバイスしてください。もちろん、改善や最適化があれば指摘してください。

4

5 に答える 5

3

交換

mcast_Addr.sin_addr.s_addr = htonl(INADDR_ANY);

mcast_Addr.sin_addr.s_addr = inet_addr (mc_addr_str);

それは私(Linux)にとって助けになります。アプリケーションごとに、1つのポートで別のmcastグループから別のmcastストリームを受け取ります。

また、VLCプレーヤーのソースを調べると、1つのポートで異なるmcastグループからの多くのmcast iptvチャネルが表示されますが、チャネルをどのように分離するかはわかりません.

于 2011-05-23T04:32:42.280 に答える
1

1 つのアプローチとして、グループへの参加方法を賢くすることです。ソケットを作成して (REUSEADDR を使用して) バインドし、IP、ポートのペアごとにグループに参加するのではなく、単一のソケットのみを作成して特定の場所にバインドします。ポートを作成し、同じソケットで複数の IGMP Join を発行します。

つまり、あなたの場合、ソケットは 1 つだけ作成され、ポートごとに 1 回バインドしますが、複数のグループに参加します。唯一の違いは、読み取り呼び出しを発行すると、いずれかのグループからパケットが取得され、区別できるように十分なデータがパケットに含まれている必要があることです。

于 2011-02-10T16:46:35.147 に答える
1

これは、複数のインターフェイスが原因であると推測しています ( でグループに参加しますINADDR_ANY)。正確なインターフェースを指定してみてください。ioctl(2)を介してインターフェイス アドレスを取得しますSIOCGIFADDR。どのインターフェイスでどのグループに参加したかを で確認しますnetstat -ng

于 2011-02-10T15:25:56.050 に答える
1

これは Linux ルーティングの機能です。セッションごとに一意のポート/マルチキャスト グループが必要です。Linux は、ポートが一致する限り、ブロードキャスト パケットなど、何でも転送します。驚くべきことに、Windows にはこの症状がありません。これがおそらく遅い理由です。

多くの商用ミドルウェア パッケージでは、互換性のためにこの要件が適用されます。たとえば、TIBCO の Rendezvous では、同じポートまたはグループの再利用は許可されません。

于 2011-02-10T19:22:44.360 に答える
1

ループバックをオフにしてみましたか?合理的な TTL があれば、少なくとも SO_REUSEPORT を使用する場合は、単一の値を取得するためにループバックは必要ありません。

int sock = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
if( sock < 0 )
    exit( -11 );

int on = true;
if( setsockopt ( sock, SOL_SOCKET, SO_REUSEPORT, & on, sizeof( on ) ) < 0 ) 
    exit( -12 );

int off = 0;
if ( setsockopt ( sock, IPPROTO_IP, IP_MULTICAST_LOOP, & off, sizeof( off ) ) < 0 )
    exit( -13 );

int ttl = 3;
if ( setsockopt ( sock, IPPROTO_IP, IP_MULTICAST_TTL, & ttl, sizeof( ttl ) ) < 0 )
    exit( -14 );

ループバックをオンのままにしておくと (デフォルトではオンになっています)、二重のパケットも取得します。

于 2013-03-06T18:07:06.300 に答える