Java中的广播消息

Posted

技术标签:

【中文标题】Java中的广播消息【英文标题】:Broadcast Message in Java 【发布时间】:2014-04-22 06:05:01 【问题描述】:

我需要一些机制来允许我将一些数据从一个 java 程序传输到同一台 PC 中的另一个程序。我已经调查了 RMI,但我希望第一个应用程序在没有第二个应用程序请求的情况下为第二个应用程序广播一些消息。在 RMI 中,只有客户端可以发起通信。

原始套接字也不可取(非常低级)。

我需要具有不同启动通信方案的 RMI 之类的东西:一台服务器在没有来自客户端的请求的情况下为多个客户端广播消息。

您能否建议我一些库/技术(用于桌面应用程序)?

【问题讨论】:

你能否提供更多关于系统必须做什么的信息,即为什么它是独立的应用程序 JAVA - make one program interact with another的可能重复 @Leon 一个应用程序生成一些数据,用作另一个应用程序的输入。所有应用程序同时工作。我的第一个应用程序必须通知第二个应用程序有关数据准备情况。每个应用程序也可以在没有另一个应用程序的情况下使用 - 因此它们是分开的。 你为什么不尝试一个带有触发器和存储过程的共享数据库呢?为什么要让消息队列复杂化? @tmporaries:使用数据库时您不必担心同步问题。只需从存储过程中调用接收应用程序的 java 方法。触发器将侦听数据准备情况并调用存储的 proc,然后调用 java 函数 【参考方案1】:

我建议您使用java messaging service 及其实现之一,例如ApacheMQ。

一个好的起点是here。

【讨论】:

【参考方案2】:

我建议使用带有触发器和存储过程的数据库。 Here is an example of calling java methods from the database。消息队列可以工作,但这是一个过于复杂的解决方案。

Here's an excerpt from an example 如何创建过程并通过触发器调用它:

First, you add the following Java method to the class DBTrigger

CREATE OR REPLACE PROCEDURE add_emp (
  emp_no NUMBER, emp_name VARCHAR2, dept_name VARCHAR2)
AS LANGUAGE JAVA 
NAME 'DBTrigger.addEmp(int, java.lang.String, java.lang.String)';

Then, you create the INSTEAD OF trigger:

CREATE OR REPLACE TRIGGER emps_trig 
INSTEAD OF INSERT ON emps
FOR EACH ROW
CALL add_emp(:new.empno, :new.ename, :new.dname);

【讨论】:

它是否仅适用于 Oracle DB?如果我能找到类似的 sqlite 解决方案,我会使用它,thanx。 只需使用 JDBC api 中的 DatabaseChangeEvent 类 对不起.. 我认为这也是 Oracle 特有的。【参考方案3】:

由于您使用 CORBA 对此进行了标记,因此您可以使用 Event Service 向所有感兴趣的客户广播通知。

【讨论】:

【参考方案4】:

使服务器能够向客户端发送信息包。根据定义,数据报是“通过网络发送的独立、自包含的消息,其到达、到达时间和内容都无法保证”。本质上,我们打开一个 DatagramSocket 以便向客户端发送 DatagramPacket 消息。我们使用数据报类(而不是标准套接字),因为它们允许我们向多个客户端广播信息,这些客户端都连接到 MulticastSocket。

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.UnknownHostException;

public class MulticastSocketServer 

    final static String INET_ADDR = "224.0.0.3";
    final static int PORT = 8888;

    public static void main(String[] args) throws UnknownHostException, InterruptedException 
        // Get the address that we are going to connect to.
        InetAddress addr = InetAddress.getByName(INET_ADDR);

        // Open a new DatagramSocket, which will be used to send the data.
        try (DatagramSocket serverSocket = new DatagramSocket()) 
            for (int i = 0; i < 100; i++) 
                String msg = "Sent message no " + i;

                // Create a packet that will contain the data
                // (in the form of bytes) and send it.
                DatagramPacket msgPacket = new DatagramPacket(msg.getBytes(),
                        msg.getBytes().length, addr, PORT);
                serverSocket.send(msgPacket);

                System.out.println("Server sent packet with msg: " + msg);
                Thread.sleep(500);
            
         catch (IOException ex) 
            ex.printStackTrace();
        
    

这里我们需要考虑的一件事是,允许我们使用 MulticastSocket 的特定地址是有限的,特别是在 224.0.0.0 到 239.255.255.255 的范围内。其中一些是保留的,例如 224.0.0.0。我们使用的地址 224.0.0.3 可以安全使用。

关于客户,我们将采取一些不同的行动。我们将创建一个客户端类,它将接受来自服务器的传入消息,然后我们将复制这个类。这里的重点是,通过使用相同的代码,我们可以无缝连接到服务器,同时拥有任意数量的客户端。

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.net.UnknownHostException;
public class MulticastSocketClient 


    final static String INET_ADDR = "224.0.0.3";
    final static int PORT = 8888;

    public static void main(String[] args) throws UnknownHostException 
        // Get the address that we are going to connect to.
        InetAddress address = InetAddress.getByName(INET_ADDR);

        // Create a buffer of bytes, which will be used to store
        // the incoming bytes containing the information from the server.
        // Since the message is small here, 256 bytes should be enough.
        byte[] buf = new byte[256];

        // Create a new Multicast socket (that will allow other sockets/programs
        // to join it as well.
        try (MulticastSocket clientSocket = new MulticastSocket(PORT))
            //Joint the Multicast group.
            clientSocket.joinGroup(address);

            while (true) 
                // Receive the information and print it.
                DatagramPacket msgPacket = new DatagramPacket(buf, buf.length);
                clientSocket.receive(msgPacket);

                String msg = new String(buf, 0, buf.length);
                System.out.println("Socket 1 received msg: " + msg);
            
         catch (IOException ex) 
            ex.printStackTrace();
        
    

首先,我们启动客户端,它会一直等待传入的信息包。一旦我们启动服务器,它就会发送信息包,客户端将接收它们并将信息打印在屏幕上

【讨论】:

【参考方案5】:

ZeroMQ 可能是您正在搜索的内容,但我只在 C、C++ 和 Python 中使用过它,所以我不完全确定它在 Java 中的使用情况。但是他们已经为他们的套接字实现了发布者-订阅者模式,并且至少 ubuntu 12.04 下的 3.2.2 版本的静态库是稳定的并且运行良好。

【讨论】:

【参考方案6】:

作为“快速修复”,将输出写入文件并让第二个应用读取文件。

这一点都不优雅,但如果你编写接口代码,你可以稍后用更好的东西替换实现。

【讨论】:

哦,当然,这是一个简单的解决方案。但我不能使用简单的 stdin/stdout 重定向 - 我的程序工作时间很长,并且它们在一个工作会话期间多次生成数据。 我不建议重定向,而是建议您从第一个应用程序中也生成一个文件,并且第二个应用程序监视文件更改并处理文件docs.oracle.com/javase/tutorial/essential/io/notification.html 可以使用这种方式。但它需要一些同步代码【参考方案7】:

一个好的解决方案是实施 OMG 数据分发标准 (DDS)。使用 DDS,只有一个具有动态发现协议的全局数据空间。参见例如RTI DDS,有一个免费的社区版。

【讨论】:

以上是关于Java中的广播消息的主要内容,如果未能解决你的问题,请参考以下文章

java 活动广播服务(发送消息)

Scratch中的广播与广播等待

广播交付和性能

RocketMQ(05)——消息的群集消费和广播消费

在java中是否有一种方法可以监听UDP广播消息并获取发送消息的源IP地址和Mac

在初始广播消息后向特定 Smack 域发送消息