2014년 3월 10일 월요일

RMI 간단한 예제소스

이전 포스팅에서 말했듯이 이번에는 간단히 RMI를 구현해 보도록 하겠다.
Remind하는 차원에서 RMI의 작성순서를 생각해 보면,
1. 인터페이스 작성
2. 서비스 해줄 class작성
3. 서버 프로그램 작성
4. 클라이언트 프로그램 작성
5. 1~4 컴파일
6. rmic.exe를 이용해 stub 생성 : ex) rmic HelloImpl
7. start rmiregistry 포트번호 : 대게 기본으로 1099를 쓴다.
8. start 3번 프로그램 실행  : 예) start java HelloServer
9. 클라이언트 프로그램 실행 : 예) java HelloClient
---------------------------------------------------------
그럼 지금부터 본격적으로 RMI를 구현해 보자.
우선 생성할 파일들의 이름을 나열해 보자.
인터페이스            : Hello.java
서비스해줄 class     : HelloImpl.java
서버 프로그램        : HelloServer.java
클라이언트 프로그램 : HelloClient.java

첫번째로 인터페이스를 구현한다.
java.rmi.RemoteException
//원격 인터페이스를 만들기 위해 Remote interface를 상속받아야 한다.
public interface Hello extends Remote{
    public String sayHello(String name) throws RemoteException;
}

두번째로 서비스 해줄 클래스를 구현한다.
import java.rmi.Naming;
import java.rmi.server.UnicastRemoteObject;
import java.rmi.RemoteException;
public class HelloImpl extends UnicastRemoteObject implements Hello{
    //기본 생성자 호출...안해줘도 되는데..ㅡㅡ;;;
    public HelloImpl() throws RemoteException{
       super();
    }
    public String sayHello(String name){
       return "Hello RMI "+name+"!!";
    }
}

세번째로 서버 프로그램을 구현한다.
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.net.MalformedURLException;
public class HelloServer{
  public static void main(String[] args){
    try{
      HelloImpl remObj = new HelloImpl();
      //매개변수로 (url, 원격객체)가 들어간다.
      Naming.rebind("rmi://localhost:1099/HelloRemote", remObj);
      System.out.println("HelloRemote객체에 대한 레지스트리 등록후 클라이언트 호출 대기");
    }catch(RemoteException e){
      System.out.println("원격 객체 처리과정에 에러 발생");
    }catch(MalformedURLException e){
      System.out.println("URL문자열 에러!!!");
    }
 }
}

네번째로 클라이언트 프로그램을 작성한다.
import java.rmi.*;
import java.net.MalformedURLException;
public class HelloClient
{
  public static void main(String[] args){
    try{
      //lookup의 return type은 remote이다.
      //따라서 remote를 상속받는 Hello가 반환된다.
      //그래서 반환받는 값으로 Object타입이나 Hello타입으로 반환 받으면 된다.
      Object obj = Naming.lookup("rmi://localhost:1099/HelloRemote");
      Hello h = (Hello)obj;
      String msg = h.sayHello("bbbb");
      System.out.println("Hello 원격 객체로부터 받은 메세지:["+msg+"]");
    }catch(RemoteException e){
      System.out.println("원격 메소드 호출 실패");
    }catch(NotBoundException e){
      System.out.println("바운딩 실패 :"+e.getMessage());
    }catch(MalformedURLException e){
      System.out.println("잘못된 URL 문자열");
    }
  }
}

다섯번째로 위에 작성한 파일들을 컴파일 한다.
->src\package명\*.java  파일들을 모두 컴파일 한다.  (javac -d . *.java)

여섯번째로 rmic.exe를 이용해 stub을 생성한다.
stub가 생성된 것을 확인할 수 있다.

일곱번째로, rmiregistry를 등록한다.
위와 같이 rmiregistry를 등록하면 빈 cmd창이 열린다. 닫으면 안된다.

여덟번째로 서버를 실행시킨다.
->bin\ 에서 start 한다
위와 같이 새로운 cmd창이 뜬다. 닫으면 안된다.

아홉번째로 client프로그램을 실행시켜서 테스트 해본다.
위와 같이 메시지가 출력되는 것을 볼 수 있다.
이상으로 간단하게 RMI를 구현해 보았다.

참고로, 구현하면서 사용한 인터페이스, 클래스에 대해 간단히 설명하겠다.
<Remote 인터페이스>
- Remote 객체
∙ 서버 측에 존재하며 실제 호출되는 method를 정의하고 있는 객체는 반드시 이 interface를 구현해야 한다.
∙ 원격지의 객체들을 RMI시스템 상에서 구분하는데 사용
∙ 이 인터페이스에 정의되어 있는 method들만이 원격지에서 호출된다.
주의) 선언되는 method는 반드시 RemoteException을 처리해야 한다.

<UnicastRemoteObject 클래스>
- RemoteServer 클래스를 상속받는 클래스.
- 자신의 생성자에게 원격 객체를 등록하는 기능을 정의
∙  원격 객체를 생성하고 노출시켜주어 client가 method를 호출할 수 있도록 도와주는 클래스
∙  이 클래스를 상속받은 원격 객체는 원격 객체가 메모리에 상주해 있는 동안에만 client로부터 method 호출을 받을 수 있다.
<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />