Связь между двумя отдельными настольными приложениями Java
Я ищу разработку двух отдельных (но связанных) настольных Java-приложений.
Я хочу, чтобы одно приложение могло инициировать другое, передавая данные, которые затем можно редактировать и передавать обратно, т.е. связь будет двухсторонней. Если другое приложение уже запущено, я хочу, чтобы они просто общались, т.е. я не хочу просто передавать аргументы через командную строку и т. Д.
Вообще говоря, какие стратегии / методы я должен рассмотреть, чтобы достигнуть этого?
11 ответов
Чтобы показать, как легко позволить двум приложениям взаимодействовать друг с другом, ознакомьтесь с этой демонстрацией сетевого буфера обмена с помощью JGroups. Просто запустите два экземпляра и начните сбрасывать файлы в один из них. Второй экземпляр мгновенно покажет те же файлы.
import java.io.Serializable;
import java.awt.*;
import java.awt.datatransfer.*;
import javax.swing.*;
import org.jgroups.*;
public class JGroupsTest {
public static void main(String[] args) throws Exception {
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.setSize(500, 300);
final DefaultListModel listModel = new DefaultListModel();
final JList panel = new JList(listModel);
panel.setBackground(new Color(128, 0, 40));
panel.setForeground(new Color(240, 240, 240));
frame.add(panel);
System.setProperty("java.net.preferIPv4Stack", "true");
final JChannel channel = new JChannel("udp.xml");
channel.connect("networkclipboard");
channel.setReceiver(new ReceiverAdapter() {
@Override
public void viewAccepted(View newView) {
frame.setTitle("Network Clipboard - " + channel.getLocalAddress());
}
@Override
public void receive(Message msg) {
listModel.addElement(msg.getObject());
}
});
panel.setTransferHandler(new TransferHandler() {
@Override
public boolean importData(JComponent comp, Transferable t) {
DataFlavor[] transferDataFlavors = t.getTransferDataFlavors();
for (DataFlavor flavor : transferDataFlavors) {
try {
Object data = t.getTransferData(flavor);
if (data instanceof Serializable) {
Serializable serializable = (Serializable) data;
Message msg = new Message();
msg.setObject(serializable);
channel.send(msg);
}
} catch (Exception e) {
e.printStackTrace();
}
}
return super.importData(comp, t);
}
@Override
public boolean canImport(TransferSupport support) {
return true;
}
@Override
public boolean canImport(JComponent comp, DataFlavor[] transferFlavors) {
return true;
}
});
}
}
Это зависит от того, как вы хотели бы общаться с этими двумя программами:
Если вам нужны только семафоры внутри процесса, создайте файл где-нибудь в / tmp и заблокируйте его.
Если вам нужен только межпроцессный синхронный обмен сообщениями (удаленный вызов процедур), RMI должен быть самым простым.
Если вам нужен асинхронный межпроцессный обмен сообщениями, JMS должен быть самым простым.
Если вам нужна межпроцессная общая память, используйте сопоставленные файлы.
Если вам нужно все вышеперечисленное, Terracotta (http://www.terracotta.org/) - самый простой способ: Java-программы на разных JVM на одном и том же или даже на разных компьютерах видят друг друга, как если бы они выполнялись внутри одной JVM на одном машина. Разделение одной программы на несколько даже не требует изменений кода - достаточно написать файл конфигурации XML.
Они могли бы каждый слушать на Socket
, Этот урок хорош для начала.
Вы должны также рассмотреть хорошие старые классические RMI.
Посмотрите на JavaGroups, это решит вашу проблему со связью, а также поможет вам определить, запущено ли другое приложение. Если приложение не запущено, вам придется запустить для него новую JVM с помощью java.lang.Runtime.exec()...
Попробуйте связаться с SocketCommunication, даже если приложение находится на одной машине.
Здесь можно найти больше информации о том, как это сделать (документация Sun/Java).
"Корпоративным" способом было бы запустить эти приложения на сервере Java EE или, по крайней мере, в среде Spring. Это также, вероятно, сильно излишне.
Если необходимо передать кучу данных, RMI сделает это.
Если вы не боитесь взломать свой собственный протокол, структуру данных и обработку ошибок, вы можете настроить сокеты сервера и клиента и обмениваться данными через них.
Я думаю, что есть некоторая грубая привлекательность альтернативы связи через файл в общем каталоге (настройка вашего собственного протокола о том, кто или когда записывает файл) или через общую базу данных. Низкотехнологичный, не очень быстрый, но очень простой и надежный. И довольно легко контролировать "общение" извне.
Для простоты, почему бы просто не использовать простые TCP-сокеты?
Я второй сокет связи и RMI. RMI немного сложнее, но интуитивнее для программиста. Это зависит от того, какой тип информации вы отправляете. Перенос необработанных байтов на другую машину может иметь больше смысла, чем запуск сервера RMI и работа со всем этим джазом...
Это зависит от того, какую связь вы хотите сделать между двумя приложениями. Если вы используете сокеты или RMI, например, оба приложения должны быть включены, чтобы произошла связь. Если тип связи, который вы хотите сделать, может быть более асинхронным, тогда вы можете использовать более подход, основанный на обмене сообщениями.
Например, ZooKeeper позволяет вам реализовать практически все, что вы хотите, поверх очень простых, но мощных примитивов. На этой странице ( http://hadoop.apache.org/zookeeper/docs/current/recipes.html) объясняется, как создавать конструкции более высокого уровня с помощью ZooKeeper.
Недостаток в том, что вам нужна другая система. Например, если вы используете JGroups, то нет.
Надеюсь это поможет
Самый простой - использовать RMI без автономной rmiregistry.
Сервер создает локальный реестр:
ServerImpl extends UnicastRemoteObject implements Server
rmiRegistry = LocateRegistry.createRegistry(2020);
rmiRegistry.bind("server", aServerImpl);
Клиент ищет его по URL-адресу rmi (аналогично corbaloc:)
String url = "rmi://localhost:2020/server";
Server server = (Server) Naming.lookup(url);
Я получил 1000 вызовов менее чем за 500 мс в цикле через одно и то же открытое соединение. Да, это миллисекунды.
Идея и образец отсюда: https://www.censhare.com/us/resources/blog/article/file-streaming-using-java-rmi
В зависимости от того, какой стиль связи вы ищете (высокая задержка, большое количество данных и т. Д.), А также от того, может ли эта система расширяться после двух систем Java, возможно, это будет система обмена сообщениями с использованием промежуточного программного обеспечения, такого как Tibco. SmartSockets.
Любая дополнительная информация о ваших настройках и ожиданиях поможет.