【问题标题】:Losing message when using multicast in local machine在本地机器中使用多播时丢失消息
【发布时间】:2013-10-27 20:28:46
【问题描述】:

我编写了一个能够通过多播地址发送/接收消息的 java 程序。 我的多播发送者代码:

public boolean multicastSender(DataTransferObject message) {

        try {

            InetAddress group = InetAddress.getByName(ip);
            MulticastSocket s = new MulticastSocket(port);
            s.joinGroup(group);

            String msg = jsh.dtoToJsonString(message);
            DatagramPacket data = new DatagramPacket(
                    msg.getBytes(), msg.length(), group, port);
            s.send(data);

            s.leaveGroup(group);
            return true;

        } catch (IOException e) {
            System.out.println(e.toString());
            e.printStackTrace();
            return false;
        }
    }

我的多播接收器代码:

public DataTransferObject multicastReceiver() {
    try {
        InetAddress group = InetAddress.getByName(ip);
        MulticastSocket s = new MulticastSocket(port);
        s.joinGroup(group);

        byte[] buffer = new byte[1000 * 1024];
        DatagramPacket data = new DatagramPacket(buffer, buffer.length);
        String jsonData;
        DataTransferObject dto;
        while (true) {
            s.receive(data);
            jsonData = new String(buffer, 0, data.getLength());
            dto = jsh.dtoFromJson(jsonData);

            if (dto == null) {
                continue;
            } else {

                return dto;

            }
        }
    } catch (IOException e) {
        System.out.println(e.toString());
        e.printStackTrace();
        return null;
    }
} 

我的程序有 4 个并行线程,它们侦听和接收来自四个不同多播地址 (224.0.0.[1->4]) 和端口 [66601->66604] 的消息。在测试中,我同时运行两个程序来测试它们之间的通信。然而我发现有时,程序 A 向多播地址发送消息,在正确的情况下,A 也会收到它,B 也会收到。但有时,我看到 A 宣布它发送了消息,但之后,A 都没有或 B 再次收到。我在本地机器上运行测试(Mac OS 10.9 with core 2 duo)。这个问题应该是因为我的电脑还是其他原因?
非常感谢。

【问题讨论】:

    标签: java multicast


    【解决方案1】:

    我在 Windows 环境中看到过这种情况。我知道这是因为网络层与 JVM 是分开的。

    这意味着一个 JVM 可以读取并处理/丢弃此消息,但其他 JVM 不会读取相同的消息,因为网络层已经将 UDP 消息传递给第一个消费者,无论有多少 JVM 订阅到同一组。这可能是也可能不是操作系统中的错误 - 这是非常主观的。就我个人而言,我认为操作系统应该跟踪注册者以复制交付,因为这是客户的意图 - 考虑到应用程序正在加入一个组以接收多播,否则这样想有点误导。操作系统应该考虑到这一点。

    我是通过经验证据得出这个结论的,可能不适用于其他平台。

    【讨论】:

    • 你有任何参考资料来支持这个说法吗?
    • 这是很久以前的事了。我可以说我亲身经历过。 TCP 堆栈不能保证每个进程至少传送一次 - 数据包保留在缓冲区中,直到有人收到它或有更多数据到达并且数据包被驱逐。完全有意义的是,数据包的传递意味着操作系统中的 comns 层不需要为其他进程/任务/线程保留它。建议您自己尝试一下。
    【解决方案2】:

    UDP,我猜是您的多播实现的基础,不保证交付。接收器或网络在过载时会丢弃数据包。您需要更高级别的协议来确保交付(谷歌可靠多播)。

    【讨论】:

    • 在本地主机上?来吧,变得真实......这是一个逃避的答案。当然,确实不能保证多播传递,但这是由于数据包冲突或路由终止或类似的原因,这不应该在 localhost 上发生。多播数据包丢弃应该在 localhost 上几乎为零。
    • 不幸的是,从我七年前的记忆来看,如果您的实现没有足够快地耗尽它(即发送者比接收者快)并且接收缓冲区已满,它也会发生在本地主机上。
    • 您所说的与组播无关,与第 7 层实现细节有关。这与“UDP 有损”的原因无关。你在谈论一个错误的应用程序。当人们谈论不能保证多播传输时,他们是在谈论网络问题以及发送方和接收方不能保证彼此之间的事情,例如 TCP 的 ACK。
    • 不是应用程序空间问题。正如您所指出的,UDP 没有一种机制来“限制”发送方作为 TCP。如果应用程序代码太慢而无法耗尽接收缓冲区,接收套接字实现应该做什么?在这种情况下,必须丢失一些定义。
    • 再一次,您只是在解释中描述了应用程序有问题。 What is the receiving socket implementation supposed to do if the application code is too slow。这是应用程序空间问题,而不是网络问题。您错误地将应用程序空间问题标记为网络问题,这不是环回接口的错。我支持我的 -1。
    猜你喜欢
    • 2015-05-07
    • 2016-08-29
    • 1970-01-01
    • 2013-02-06
    • 2019-07-12
    • 1970-01-01
    • 2018-09-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多