2009-07-27 2 views
8

서버에서 장기 실행 프로세스를 시작하는 클라이언트가 있습니다. 정기적 인 간격으로 백그라운드에서 어떤 일이 일어나고 있는지 사용자에게 보여주고 싶습니다. 가장 간단한 방법은 서버를 폴링하는 것이지만 Observer 패턴을 구현할 방법이 없는지 궁금합니다. 안타깝게도 RMI를 사용하여 서버와 통신하고 있으므로 클라이언트를 RMI 서버로 전환해야합니다.Java RMI를 사용하여 Observer 패턴을 구현하는 방법은 무엇입니까?

다른 방법이 있습니까?

+1

을 제공합니다 ... RMI는 좀 짜증! :) – JohnIdol

답변

1

나는 당신이 아무것도 놓치고 있다고 생각하지 않습니다. 두 가지 방법은 주기적으로 서버를 호출하고 상태 (폴링)를 확인하거나 서버가 주기적으로 호출하는 콜백을 등록하는 것입니다 (클라이언트는 메소드를 노출해야합니다). IMO, 폴링은 이것을 처리하는 데있어 합리적인 방법입니다.

3

일반적으로 RMI는 양방향 통신을 지원할 수 있습니다. (그리고 예, RMI는 PITA로 설정하고 다른 작업을 수행합니다.)

그러나 CGI 스크립트 (!)를 통해 작동하는 HTTP 전송은 지원하지 않습니다.

+0

Sun에서 제공 한 실행 파일을 사용하는 대신 LocateRegistry.createRegistry()를 사용하여 내 코드에서 서버를 시작할 때 여전히 사실입니까? –

+0

+1 "(예, RMI는 PITA로 설정하고 다른 작업을 수행합니다.)"제 학교에 알려주십시오. – Luc

2

여기에 모든 해답을 통합, 나는 레지스트리

클라이언트는 RMI 레지스트리에서 서버의 스텁을 얻는다
  1. 를 사용하여 스텁을 노출하는 서버와 클라이언트와 서버 사이에이 방법으로 RMI를 구현
  2. 그런 다음 클라이언트는 서버의 addObserver 메소드에 Observer라는 스텁을 넣습니다.
  3. 서버가이 스텁을 사용하여 클라이언트에 통지합니다.

다음 코드 의지 나뿐만 아니라이 작업을 수행하려고하고 내가 같은 결론에 도달했습니다 더 나은 아이디어를

import java.rmi.*; 
import java.rmi.registry.*; 
import java.rmi.server.*; 
import java.util.Observable; 
import java.util.Observer; 
import java.net.*; 

import javax.rmi.ssl.SslRMIClientSocketFactory; 
import javax.rmi.ssl.SslRMIServerSocketFactory; 

interface ReceiveMessageInterface extends Remote 
{ 
    /** 
    * @param x 
    * @throws RemoteException 
    */ 
    void receiveMessage(String x) throws RemoteException; 

    /** 
    * @param observer 
    * @throws RemoteException 
    */ 
    void addObserver(Remote observer) throws RemoteException; 
} 

/** 
* 
*/ 
class RmiClient extends UnicastRemoteObject 
{ 
    /** 
    * @param args 
    */ 
    static public void main(String args[]) 
    { 
     ReceiveMessageInterface rmiServer; 
     Registry registry; 
     String serverAddress = args[0]; 
     String serverPort = args[1]; 
     String text = args[2]; 
     System.out.println("sending " + text + " to " + serverAddress + ":" + serverPort); 
     try 
     { // Get the server's stub 
      registry = LocateRegistry.getRegistry(serverAddress, (new Integer(serverPort)).intValue()); 
      rmiServer = (ReceiveMessageInterface) (registry.lookup("rmiServer")); 

      // RMI client will give a stub of itself to the server 
      Remote aRemoteObj = (Remote) UnicastRemoteObject.exportObject(new RmiClient(), 0); 
      rmiServer.addObserver(aRemoteObj); 

      // call the remote method 
      rmiServer.receiveMessage(text); 
      // update method will be notified 
     } 
     catch (RemoteException e) 
     { 
      e.printStackTrace(); 
     } 
     catch (NotBoundException e) 
     { 
      System.err.println(e); 
     } 
    } 

    public void update(String a) throws RemoteException 
    { 
     // update should take some serializable object as param NOT Observable 
     // and Object 
     // Server callsbacks here 
    } 
} 

/** 
* 
*/ 
class RmiServer extends Observable implements ReceiveMessageInterface 
{ 
    String address; 
    Registry registry; 

    /** 
    * {@inheritDoc} 
    */ 
    public void receiveMessage(String x) throws RemoteException 
    { 
     System.out.println(x); 
     setChanged(); 
     notifyObservers(x + "invoked me"); 
    } 

    /** 
    * {@inheritDoc} 
    */ 
    public void addObserver(final Remote observer) throws RemoteException 
    { 
     // This is where you plug in client's stub 
     super.addObserver(new Observer() 
     { 
      @Override 
      public void update(Observable o, 
       Object arg) 
      { 
       try 
       { 
        ((RmiClient) observer).update((String) arg); 
       } 
       catch (RemoteException e) 
       { 

       } 
      } 
     }); 
    } 

    /** 
    * @throws RemoteException 
    */ 
    public RmiServer() throws RemoteException 
    { 
     try 
     { 
      address = (InetAddress.getLocalHost()).toString(); 
     } 
     catch (Exception e) 
     { 
      System.out.println("can't get inet address."); 
     } 
     int port = 3232; 
     System.out.println("this address=" + address + ",port=" + port); 
     try 
     { 
      registry = LocateRegistry.createRegistry(port); 
      registry.rebind("rmiServer", this); 
     } 
     catch (RemoteException e) 
     { 
      System.out.println("remote exception" + e); 
     } 
    } 

    /** 
    * 
    * @param args 
    */ 
    static public void main(String args[]) 
    { 
     try 
     { 
      RmiServer server = new RmiServer(); 
     } 
     catch (Exception e) 
     { 
      e.printStackTrace(); 
      System.exit(1); 
     } 
    } 
} 
+0

RmiServer 클래스가 addObserver를 구현하면 코드에서 RmiClient 클래스를 서버에서 사용할 수 있습니다. RmiClient 클래스가 클라이언트와 서버 모두에 정의되어 있습니까? – KUN

관련 문제