2016-11-08 3 views
0

Мы пытаемся создать простую программу чата, используя 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; 
      } 
+0

Итак, у вас есть 2-проводная связь? Клиент может вызывать методы на сервере и наоборот? – Antoniossss

+0

@Antoniossss Да, возможно, не лучший способ сделать чат-программу. Мне нужно что-то для клиента, чтобы сообщить серверу, что он отправил сообщение, и что-то для сервера, чтобы передать это сообщение всем другим клиентам. По крайней мере, я это понимаю. – Wilmz

+0

В общем, вам нужна архитектура PUSH, а RMI - типичный PULL. Instified io изобретать колесо, почему бы вам не использовать уже существующие и бесплатные технологии для общения в чате (и многое другое!), Например, XMPP? В прошлом я успешно создал приложение чата на основе XMPP и использовал сервер OpenFire в качестве брокера сообщений. Вы также можете использовать очередь сообщений, чтобы достичь архитектуры PUSH с целью использования приложений чата. – Antoniossss

ответ

0

Для способа RMI, не думают стороны, как клиент-сервер, а remote service и caller.

Таким образом, caller должен быть способен подключиться через TCP к remote service, чтобы выполнять вызов удаленного метода (RMI). Поэтому в вашем случае переадресация портов должна быть установлена ​​с обеих сторон. Как это может быть трудным (например, клиент может находиться за NAT, не удалось - как в вашем случае), лучше угрозы RMI больше как REST сервис - это только одна сторона вызова remote service

Кроме пересылки 1099 ведьма является RMI вы также должны пересылать порты, используемые экспортируемыми объектами. Реестр RMI содержит только информацию о том, как подключиться к фактическому обработчику обработанных объектов.

Смежные вопросы