2016-11-08 4 views
0

푸시 구성으로 RMI를 사용하여 간단한 채팅 프로그램을 만들려고합니다. 이 프로그램은 내부 네트워크에서 작동하지만, 외부 네트워크에있는 서버에 프로그램을 실행하려고 할 때, 우리는 오류 얻을 :외부 네트워크에서 RMI Chat 프로그램 푸시 구성이 작동하지 않습니다.

java.rmi.ConnectException: Connection refused to host: 192.168.1.13; 
Caused by: java.net.ConnectException: Connection timed out: connect 

클라이언트가 방법 '방송을 호출 할 때 오류가 발생합니다 (문자열 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); 
} 

클라이언트 : RMI의 방식에 대한

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

그래서 양방향 연결이 되었습니까? 클라이언트는 서버에서 메소드를 호출 할 수 있으며 그 반대도 가능합니다. – Antoniossss

+0

@Antoniossss 예, 채팅 프로그램을 만드는 가장 좋은 방법은 아닙니다. 클라이언트가 메시지를 보내는 서버에 알려주고, 서버가 다른 모든 클라이언트에게 메시지를 브로드 캐스트하기위한 것이 필요합니다. 적어도 그것은 그것이 내가 이해하고있는 것입니다. – Wilmz

+0

일반적으로 RMI는 일반적인 PULL이지만 PUSH 아키텍처가 필요합니다. 바퀴를 재발 명하면서, 기존의 XMPP처럼 채팅과 유사한 채팅 기술에 기존 기술을 자유롭게 사용하는 이유는 무엇입니까? 과거에는 XMPP 기반의 채팅 응용 프로그램을 만들고 메시지 브로커로 OpenFire 서버를 사용했습니다. 메시지 대기열을 사용하여 채팅 응용 프로그램의 용도로 PUSH 아키텍처를 구현할 수도 있습니다. – Antoniossss

답변

0

, 클라이언트 - 서버 등의 측면을 생각하지 말아 아니라 remote servicecaller.

그래서 caller은 원격 메소드 호출 (RMI)을 수행하기 위해 TCP를 통해 remote service에 연결할 수 있어야합니다. 따라서 귀하의 경우 포트 포워딩을 양쪽에 적절히 설정해야합니다. 문제가 될 수 있으므로 (예 : 고객이 관리하지 않는 NAT 뒤에있을 수 있습니다.) RMI 서비스와 마찬가지로 RMI를 위협하는 것이 좋습니다. remote service

전달 외에도 1099 RMI가 허위입니다. 레지스트리 포트에서 내 보낸 개체가 사용하는 포트도 전달해야합니다. RMI 레지스트리는 실제 내 보낸 객체 핸들러에 연결하는 방법에 대한 정보 만 보유합니다.