6

我有几台嵌入式机器正在侦听并将 rtp 音频数据流式传输到多播组。它们连接到智能管理交换机 (Netgear GS108Ev2),该交换机在其端口上执行基本的 igmp 侦听和多播过滤,这样我的 (W)LAN 的其余部分就不会被淹没。

开始时一切正常约 500-520 秒。之后,他们将不再收到任何数据,直到他们离开并再次加入该组。我猜这个开关在超时后“忘记”了加入。

有什么方法可以刷新组成员身份,即让交换机知道还有人在听,而不会丢失数据包?

系统信息:

Arch: blackfin

# cat /proc/version
Linux version 2.6.28.10-ADI-2009R1-uCBF54x-EMM
(gcc version 4.3.3 (ADI) ) #158 PREEMPT Tue Jun 5 20:05:42 CEST 2012
4

4 回答 4

3

这就是多播/IGMP 协议的工作方式。客户必须通过发送会员报告定期加入群组,否则将假定他在短暂的超时后离开了群组。但是,这些报告通常仅在从本地多播路由器接收到成员资格查询时才发送。您的客户要么没有收到查询,要么没有回复报告。

尝试使用像 wireshark 这样的工具来查看哪些 IGMP 数据包是通过您的网络发送的。

于 2012-06-06T14:48:21.947 回答
1

正如 scai 已经解释的那样,您需要一个IGMP 查询器来发送.Membership Queries

如果您无法配置路由器来执行此操作,则可以使用其中一台计算机。看到运行一个完整的多播路由守护进程是多么的大材小用(我从来没有这样做过),我建议你尝试滥用igmpproxy

首先创建一个虚拟上游接口(这不是持久的!):

ip tap add dev tap6 mode tap

编写 igmpproxy.conf:

# Dummy upstream interface.
phyint tap6 upstream  ratelimit 0  threshold 1

# Local interface.
phyint eth0 downstream  ratelimit 0  threshold 1

# Explicitly disable any other interfaces (yes, it sucks).
phyint NAME disabled
...

最后启动 igmpproxy(以 root 身份):

igmpproxy -v /path/to/igmpproxy.conf
于 2012-06-06T19:32:56.657 回答
0

如果您的嵌入式设备运行的是 linux,您需要关闭它们上的反向数据包过滤器,否则它们将不会响应组成员资格查询。在这种情况下,上游交换机将假定没有人在收听该多播并将其关闭。

于 2014-07-24T08:02:47.543 回答
0

我有同样的问题,wifi 上的多播在 260 秒后丢失,我通过在套接字上添加 AddSourceMembership 用我的应用程序解决了这个问题。

private void StartListner(IPAddress sourceIp, IPAddress multicastGroupIp, IPAddress localIp, int port)
{
    try
    {
        Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

        IPEndPoint localEndpoint = new IPEndPoint(localIp, port);
        socket.Bind(localEndpoint);

        byte[] membershipAddresses = new byte[12]; // 3 IPs * 4 bytes (IPv4)
        Buffer.BlockCopy(multicastGroupIp.GetAddressBytes(), 0, membershipAddresses, 0, 4);
        Buffer.BlockCopy(sourceIp.GetAddressBytes(), 0, membershipAddresses, 4, 4);
        Buffer.BlockCopy(localIp.GetAddressBytes(), 0, membershipAddresses, 8, 4);
        socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddSourceMembership, membershipAddresses);

        try
        {
            byte[] b = new byte[1024 * 2];
            int length = socket.Receive(b);
        }
        catch { }
    }
    catch (Exception ex)
    {
        logger.Error("Exception: " + ex);
    }
}
于 2019-11-05T08:46:55.103 回答