多播接收器套接字中的重复数据包 [英] Duplicate packets in Multicast Receiver Socket

查看:130
本文介绍了多播接收器套接字中的重复数据包的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下MulticastReceiver实现中似乎存在一个错误.

There seems to be a bug in the following MulticastReceiver implementation.

在为< 224.0.25.46,13001>和< 224.0.25.172,13001>创建两个实例时,我在每个流中两次获得每个数据包.有指针吗?我的猜测是REUSEADDR吗?

On creating two instances for <224.0.25.46,13001> and <224.0.25.172,13001>, I get each packet twice in each stream. Any pointers ? My guess is 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;
}

请提出建议,当然,请指出可以进行的任何改进和优化.

Please advise, and of course, please point out any improvements, optimizations that can be made.

推荐答案

您可以采取的一种方法是对如何加入组保持聪明,而不是创建套接字,绑定(使用REUSEADDR)然后加入组以实现以下目的:每对IP,端口仅构造一个套接字并绑定到给定的端口,然后在同一套接字上发出多个IGMP连接.

One approach you can take is to be smart about how you join the groups, so rather than create a socket, bind (with REUSEADDR) and then join group for each pair of ip, port, only construct a single socket and bind to a given port, and then issue multiple IGMP joins on the same socket.

即在您的情况下,仅创建一个套接字,每个端口绑定一次,但是您加入了多个组.唯一的区别是,发出读取呼叫时,您将从一个或另一个组中获得一个数据包,并且您需要在数据包中包含足够的数据以使您能够区分.

i.e. in your case, only one socket is created, you bind once per port, but you join multiple groups. The only difference is that when you issue the read call, you will get a packet from one or the other group and you need to have enough data in the packet to allow your to distinguish.

这篇关于多播接收器套接字中的重复数据包的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆