【问题标题】:multiple multicast on multiple interfaces多个接口上的多个多播
【发布时间】:2012-06-27 20:54:28
【问题描述】:

操作系统:CentOS 5.5
语言:C++

我对此进行了相当多的研究,但我真的找不到任何与我所拥有的精确设置相关的文章。这是一个非常具体的设置,所以我将尽我所能描述我在做什么以及我正在尝试做什么。

我有一台带有 2 个以太网端口(eth0 和 eth1)的计算机。每个人同时接收不同的多播广播。所以 1 个多播 IP 地址和端口将指向 eth0,另一个多播 IP 地址和端口将指向 eth1。

我正在编写一个程序,旨在侦听给定的多播 IP 地址和端口。

目标是能够启动程序并收听其中一个多播,同时启动该程序的第二个实例来收听另一个多播。该程序本身仅设计为一次收听 1 个多播。

但是,我似乎无法同时运行这两个程序。

使用“路由”命令,我已经能够设置路由表,我可以在其中接收 1 个流,但不能接收另一个。我一次只能播放 1 个流,但不能同时播放。

eth0 连接到:10.10.20.50 -- 该接口的多播是 225.0.7.10 端口 51007 eth1 连接到:192.168.20.21 -- 该接口的多播是 225.0.8.10 端口 51008

如果我执行路由命令,“route add default gw 1​​0.10.20.50 eth0”我可以接收到该地址上的多播就可以了

但一旦我添加“route add default gw 1​​92.168.20.21 eth1”,我就无法再在 10.10.20.50 接口上接收多播。

绑定套接字或设置 sockopts 时我没有收到任何错误...该程序只是简单地阻塞了 recv 调用并且永远不会收到消息。

我已经尝试了各种路由命令的组合来支持这一点,并且我在连接代码中也做了一些不同的事情来解决这个问题,但没有运气。这是我当前的连接代码:

  //Create the UDP socket, check to make sure it was created successfully
  cout << "Initializing Connection..." << endl ;
  m_socket = socket ( AF_INET , SOCK_DGRAM , IPPROTO_UDP ) ;

  if( m_socket == -1 )
  {
    cout << "ERROR CREATING SOCKET: " << strerror(errno) << endl ;
    return false ;
  }

  cout << "Socket Created" << endl;

  //Setup socket binding information
  sockaddr_in addr ;
  bzero  ( ( char* ) &addr , sizeof ( addr ) ) ;
  addr . sin_family       = AF_INET ;
  addr . sin_addr.s_addr  = inet_addr(interface_addr) ; //10.10.20.50 or 192.168.20.21
  addr . sin_port         = htons ( port ) ;            //51007 or 51008

  //bind the socket, check for errors
  int result = bind ( m_socket , ( struct sockaddr* ) &addr , sizeof ( addr ) ) ;

  if ( result == -1 )
  {
    cout << "ERROR BINDING PORT: " << strerror ( errno ) << endl;
    shutdown ( m_socket , SHUT_RDWR ) ;
    return false ;
  }

  cout << "Socket Bound" << endl;

  //subscribe to the supplied IP address and port to listen on
  in_addr host_addr ;
  inet_pton ( AF_INET , ip_addrs . c_str () , & ( host_addr ) ) ;

  struct ip_mreq mreq;
  mreq . imr_multiaddr = host_addr ;       // multicast address 225.0.7.10 or 225.0.8.10
  mreq . imr_interface = addr . sin_addr ; //the 10.10.20.50 or 192.168.20.21 specified above

  result = setsockopt ( m_socket , IPPROTO_IP , IP_ADD_MEMBERSHIP, &mreq , sizeof(mreq) ) ;

  if ( result == -1 )
  {
    cout << "ERROR SETTING SOCKOPT SUBSCRIPTION: " << strerror(errno) << endl ;
    printSocketError();
    shutdown ( m_socket , SHUT_RDWR ) ;
    return false ;
  }

  /*
   * Read from the socket to get the initial bit of information we need so the
   * buffers can get allocated correctly, and the width and height of the application
   * can be defined.
   */
  cout << "Attempting to read from the socket..." << endl;
  MyPacket pckt ;
  recv ( m_socket , &pckt , sizeof ( pckt ) , MSG_PEEK ) ;

  cout << "Data Received... processing" << endl ;

我也尝试使用 ip_mreqn 结构手动指定接口,并使用 setsockopt 进行 SOL_BINDTODEVICE 设置(eth0 或 eth1),但遇到了与以前相同的问题,如果我有特定的路由,我只能连接它设置...即使这样,也只有 1 个会收到,而另一个不会收到。

重申...我需要同时运行该程序的 2 个副本..每个副本都在侦听来自特定接口的自己指定的多播地址。

【问题讨论】:

    标签: c++ linux networking multicast


    【解决方案1】:

    您需要设置两个不同的路由,因此不同的组被路由到(并因此被监听)给定的接口:

    root:~# route add -net 225.0.7.10 netmask 255.255.255.255 dev eth0
    root:~# route add -net 225.0.8.10 netmask 255.255.255.255 dev eth1
    

    然后,当您的程序运行时,您应该能够看到在netstat -ng 的哪个接口上收听了哪些组。

    编辑0:

    编辑 1:

    获取我提到的 UNP 书籍的源代码,它是 here。在解压后的存档中查看unpv13e/lib目录,读取mcast_join.c文件。

    【讨论】:

    • 尼古拉,感谢您的回复。我之前实际上已经尝试过执行这些命令,但是当我执行它们时出现“网络掩码与路由地址不匹配”错误
    • 好的,那些命令执行成功...现在我的问题是我应该实际绑定到哪个地址? INADDR_ANY? 10.10.20.51/192.168.20.21?另外..我应该怎么做我的sockopt?我需要担心 SOL_BINDTODEVICE 和 IP_ADD_MEMBERSHIP 吗?
    • 绑定群地址,不用BINDTODEVICE
    • 感谢您的意见 Nikolai,仍然有问题。我已经用你的路由命令在 c++ 代码中尝试了这些配置: BIND:192.168.20.21/10.10.20.50 端口:51008/51007 MREQ:接口 192.168.20.21/10.10.20.50 地址:225.0.8.10/225.0.7.10 我也有也尝试绑定到多播地址,但没有成功。该程序仍然挂在recv上。我注意到如果我发送垃圾邮件“ifconfig”,我可以看到程序运行时流量大小不断增加,并在程序关闭时停止
    【解决方案2】:

    宁可这样做—— 1. 创建一个类。 2. 具有在该类中创建和绑定 IP 和端口的功能。 3. 使用该类 Object 从主函数调用该函数两次。

    要验证结果,您可以使用命令 netstat -g,它将显示与您的多播 IP 对应的两个实例。

    如果您愿意,我可以编写代码,但请先自己尝试编写代码。

    【讨论】:

      猜你喜欢
      • 2012-03-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多