Мы пытаемся создать простую программу чата, используя RMI с конфигурацией push. Программа работает на внутренней сети, но когда пытались запустить программу с сервера на внешней сети, мы получаем ошибку:RMI Chatprogram push конфигурация на внешней сети не работает
java.rmi.ConnectException: Connection refused to host: 192.168.1.13;
Caused by: java.net.ConnectException: Connection timed out: connect
ошибка возникает, когда клиент вызывает метод «Broadcast (String s) 'на интерфейсе «IChatServer» Этот метод расположен на сервере и вызывает других клиентов, подписанных как слушатель на сервере.
Наш клиент может подключиться к серверу. Он может получить привязки из реестра и методы вызова с сервера.
Но когда сервер пытается вызвать метод от клиента, мы получаем эту ошибку.
На сервере переадресован порт 1099, а в брандмауэре разрешен порт 1099.
Есть ли способ сделать это возможным (используя RMI)? Нужно ли переадресовывать порты на стороне клиента?
Сервер:
try {
String theIp = serverHostExternalIp;
System.setProperty("java.rmi.server.hostname", theIp);
//Implemented this so no random ports will be used
RMISocketFactory.setSocketFactory(new FixedPortRMISocketFactory());
registry = LocateRegistry.createRegistry(PORT_NUMBER);
publisher = new RemotePublisher();
publisher.registerProperty(BINDING_NAME);
UnicastRemoteObject.unexportObject(server, true);
UnicastRemoteObject.exportObject(server, PORT_NUMBER);
UnicastRemoteObject.unexportObject(publisher, true);
UnicastRemoteObject.exportObject(publisher, PORT_NUMBER);
registry.rebind(BINDING_NAME, server);
registry.rebind(PUBLISH_NAME, publisher);
} catch (RemoteException ex) {
System.err.println("[Server] Cannot bind student administration");
System.err.println("[Server] RemoteException: " + ex.getMessage());
}
IChatServer:
public synchronized void tryConnect(String s, IChatClient client) throws RemoteException {
System.out.println("[Server] User connected: " + s);
}
public synchronized void broadcast(String s) throws RemoteException {
// When this line is called, no errors occur, and the string is printed correctly.
System.out.println("[Message] " + s);
//on this line, the server tries to reach to all the clients (all listeners)
//This line of code will generate an error.
publisher.inform(BINDING_NAME, null, s);
}
Клиент:
try {
registry = LocateRegistry.getRegistry(ipAddress, PORT_NUMBER);
mycs = (IChatServer) registry.lookup(BINDING_NAME);
//This method is located on the server and is called without errors.
mycs.tryConnect(userid, this);
publisher = (IRemotePublisherForListener) registry.lookup(PUBLISH_NAME);
publisher.subscribeRemoteListener(this, BINDING_NAME);
} catch (RemoteException ex) {
System.err.println("[Client] Cannot lookup or subscribe publisher");
System.err.println("[Client] RemoteException: " + ex.getMessage());
registry = null;
} catch (NotBoundException e) {
System.err.println("[Client] Cannot lookup or subscribe publisher");
System.err.println("[Client] NotBoundException: " + e.getMessage());
registry = null;
}
Итак, у вас есть 2-проводная связь? Клиент может вызывать методы на сервере и наоборот? – Antoniossss
@Antoniossss Да, возможно, не лучший способ сделать чат-программу. Мне нужно что-то для клиента, чтобы сообщить серверу, что он отправил сообщение, и что-то для сервера, чтобы передать это сообщение всем другим клиентам. По крайней мере, я это понимаю. – Wilmz
В общем, вам нужна архитектура PUSH, а RMI - типичный PULL. Instified io изобретать колесо, почему бы вам не использовать уже существующие и бесплатные технологии для общения в чате (и многое другое!), Например, XMPP? В прошлом я успешно создал приложение чата на основе XMPP и использовал сервер OpenFire в качестве брокера сообщений. Вы также можете использовать очередь сообщений, чтобы достичь архитектуры PUSH с целью использования приложений чата. – Antoniossss