刷新组播组成员资格

时间:2012-06-06 11:41:49

标签: c linux multicast uclinux

我有几台嵌入式计算机正在监听并将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 个答案:

答案 0 :(得分:3)

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

尝试使用wireshark之​​类的工具,以查看通过网络发送的IGMP数据包。

答案 1 :(得分:1)

您需要 IGMP查询器才能发送Membership Queries,正如scai已经解释的那样。

如果您无法配置路由器来执行此操作,则可以使用其中一台计算机。看到如何运行完整的多播路由守护程序会有点过分(我从来没有这样做过),我建议您尝试滥用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

答案 2 :(得分:0)

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

答案 3 :(得分:0)

我遇到了同样的问题,260秒后wifi上的多播丢失了,我通过在套接字上添加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);
    }
}