Chapter 17. RMI Mingyu Lim Collaborative Computing Systems Lab, School of Internet & Multimedia Engineering Konkuk University, Seoul, Korea
학습목표 RMI란 RMI 구조 RMI는어떻게동작하는가 로컬객체를원격객체로변경하기 RMI를이용한계산기애플리케이션 RMI를이용한채팅애플리케이션 RMI-IIOP RMI-IIOP 예제 2009 Collaborative Computing Systems Lab, Konkuk Univ. 2
RMI 란 기존소켓프로그래밍 서버 / 클라이언트간프로토콜을지키며통신 프로토콜이복잡해질수록소켓프로그래밍또한복잡 RMI (Remote Method Invocation) 원격의객체메소드를로컬컴퓨터의메소드호출과같은방식 내부프로토콜과상관없이메소드의인자와반환형식만맞춰주면됨 유사방식 CORBA, DCOM, RPC 2009 Collaborative Computing Systems Lab, Konkuk Univ. 3
RMI 구조 로컬객체메소드호출 Object o =??? 같은 JVM 의힙내에호출자와호출대상존재 원격객체메소드호출 Object o =??? 형식불가 호출자와호출대상이다른 JVM 에존재 RMI 클라이언트측스텁모듈과서버측스켈레톤모듈통해원격객체의메소드를로컬메소드처럼호출가능 2009 Collaborative Computing Systems Lab, Konkuk Univ. 4
RMI 구조 클라이언트객체 서버객체 스텁 네트워크 스켈레톤 RMI 스텁 / 스켈레톤 원격객체메소드를로컬메소드호출하듯이처리 클라이언트에서스텁의메소드호출 스텁은원격의서버측스켈레톤에접속하여메소드명, 인자전달 서버는스켈레톤통해요청메소드정보를알아내어처리 반환값은다시스켈레톤을통해클라이언트스텁으로전달 스텁 / 스켈레톤은 J2SDK 내의 rmic 컴파일러로생성 2009 Collaborative Computing Systems Lab, Konkuk Univ. 5
RMI 는어떻게동작하는가 RMI 통신순서 1) 서버가원격객체를 RMI Registry에등록 2) 클라이언트가 RMI Registry에서원격객체룩업 3) 클라이언트가원격객체이용하여원격메소드호출 서버에서등록객체가스텁 2009 Collaborative Computing Systems Lab, Konkuk Univ. 6
로컬객체를원격객체로변환 원격객체를이용한 Hello 애플리케이션작성순서 1) 원격인터페이스작성 2) 원격인터페이스실제구현하는원격클래스작성해당클래스는 java.rmi.server.unicastremoteobject 상속 3) 원격객체를 rmiregistry 에등록하기위한애플리케이션작성 4) 원격객체를이용하는클라이언트작성 5) 스텁과스켈레톤생성 (rmic 이용 ) 6) 원격객체를 rmiregistry 에등록 7) 클라이언트애플리케이션실행 2009 Collaborative Computing Systems Lab, Konkuk Univ. 7
로컬객체를원격객체로변환 1) 원격인터페이스작성 RMI 원격인터페이스상속 (java.rmi.remote) 인터페이스내메소드는반드시 RemoteException 을 throws 메소드에전달하는인자와반환값은기본형이거나 java.io.seriablizable 인터페이스구현한것 import java.rmi.remote; import java.rmi.remoteexception; public interface RMIHello extends Remote public String hello(string name) throws RemoteException; 2009 Collaborative Computing Systems Lab, Konkuk Univ. 8
로컬객체를원격객체로변환 2) 원격인터페이스를구현하는원격객체작성 Java.rmi.server.UnicastRemoteObject 상속 원격인터페이스에있는메소드실제구현 Java.rmi.RemoteException 을 throws 하는기본생성자 원격인터페이스에있는메소드구현하는경우 java.rmi.remoteexception 을 throws 하게한다 import java.rmi.remoteexception; import java.rmi.server.unicastremoteobject; public class RMIHelloImpl extends UnicastRemoteObject implements RMIHello public RMIHelloImpl() throws RemoteException public String hello(string name) throws RemoteException return "Hello "+name+"!"; 2009 Collaborative Computing Systems Lab, Konkuk Univ. 9
로컬객체를원격객체로변환 3) 원격객체를등록하기위한애플리케이션작성 import java.rmi.naming; import java.rmi.rmisecuritymanager; public class RMIHelloBind public static void main(string[] args) RMISecurityManager sm = new RMISecurityManager(); System.setSecurityManager(sm); try RMIHelloImpl obj = new RMIHelloImpl(); Naming.rebind("//127.0.0.1:2000/hello", obj); System.out.println("Hello 객체가 catch(exception e) System.out.println(" 등록이안되었습니다 신뢰할수없는서버로부터스텁적재시자신을보호하기위해사용 객체가 Registry에등록되었습니다."); 안되었습니다." + e.tostring()); Rmiregistry 에 Hello 이름으로등록 2009 Collaborative Computing Systems Lab, Konkuk Univ. 10 10
로컬객체를원격객체로변환 4) 원격객체를실제로이용하는클라이언트작성 import java.rmi.naming; public class RMIHelloClient public static void main(string[] args) Hello원격객체 lookup try Object obj = Naming.lookup("//127.0.0.1:2000/hello"); RMIHello hi = (RMIHello)obj; RMIHello인터페이스로형변환 String msg = hi.hello(" 김성박 "); System.out.println(msg); 로컬객체메소드처럼사용 catch(exception e) System.out.println(e); 2009 Collaborative Computing Systems Lab, Konkuk Univ. 11 11
로컬객체를원격객체로변환 5) 컴파일과스텁, 스켈레톤생성 소스컴파일 Javac *.java 스텁 / 스켈레톤생성 rmic RMIHelloImpl (class file 있는디렉토리에서 ) 클래스파일분리 Client 디렉토리 RMIHello.class, RMIHelloImpl.class, RMIHelloClient.class, RMIHelloImpl_Stub.class Server 디렉토리 RMIHello.class, RMIHelloImpl.class, RMIHelloBind.class, RMIHelloImpl_Skel.class(or RMIHelloImpl_Stub.class) 2009 Collaborative Computing Systems Lab, Konkuk Univ. 12
로컬객체를원격객체로변환 6) rmiregistry 실행과 rmiregistry 에원격객체등록 (Server 디렉토리 ) rmiregistry 실행 rmiregistry 2000 (2000 포트로실행 ) Policy 파일작성 grant ; 원격객체등록 //Allow everything for now permission java.security.allpermission; Java Djava.security.manager Djava.security.policy=policy RMIHelloBind 2009 Collaborative Computing Systems Lab, Konkuk Univ. 13
로컬객체를원격객체로변환 7) 원격객체이용하는클라이언트실행 ( 클라이언트디렉토리 ) java RMIHelloClient 2009 Collaborative Computing Systems Lab, Konkuk Univ. 14 14
RMI 를이용한계산기애플리케이션 4 칙연산가능한애플리케이션작성순서 1) 계산기원격인터페이스작성 2) 계산기원격인터페이스를구현하는원격클래스작성 java.rmi.server.unicastremoteobject 상속 3) 원격객체를 rmiregistry 에등록하는애플리케이션작성 4) 원격객체를이용하는클라이언트작성 5) 스텁과스켈레톤생성 (rmic 이용 ) 6) 원격객체를 rmiregistry 에등록 7) 클라이언트애플리케이션실행 2009 Collaborative Computing Systems Lab, Konkuk Univ. 15
RMI 를이용한계산기애플리케이션 1) 계산기원격인터페이스작성 import java.rmi.*; public interface Calculator extends Remote public int sum(int i, int j) throws RemoteException; public int multiply(int i, int j) throws RemoteException; public int divide(int i, int j) throws RemoteException, ArithmeticException; public int subtract(int i, int j) throws RemoteException; 2009 Collaborative Computing Systems Lab, Konkuk Univ. 16 16
RMI 를이용한계산기애플리케이션 2) 계산기원격인터페이스를구현하는원격클래스작성 import java.rmi.remoteexception; import java.rmi.server.unicastremoteobject; public class CalculatorImpl extends UnicastRemoteObject implements Calculator public CalculatorImpl() throws RemoteException public int divide(int i, int j) throws RemoteException, ArithmeticException if(j == 0) throw new ArithmeticException("0 으로나눌수없습니다."); return i / j; public int subtract(int i, int j) throws RemoteException return i - j; 2009 Collaborative Computing Systems Lab, Konkuk Univ. 17 17
RMI 를이용한계산기애플리케이션 3) 원격객체를 rmiregistry 에등록하는애플리케이션작성 import java.rmi.naming; import java.rmi.rmisecuritymanager; public class CalculatorBind public static void main(string[] args) RMISecurityManager sm = new RMISecurityManager(); System.setSecurityManager(sm); try CalculatorImpl obj = new CalculatorImpl(); Naming.rebind("//127.0.0.1:2000/calculator", obj); System.out.println("Calculator 객체가 Registry에등록되었습니다."); catch(exception e) System.out.println(" 등록이안되었습니다." + e.tostring()); 2009 Collaborative Computing Systems Lab, Konkuk Univ. 18 18
RMI 를이용한계산기애플리케이션 4) 원격객체를사용하는클라이언트작성 Calculator 원격객체 lookup Object obj = Naming.lookup("//127.0.0.1:2000/calculator"); Calculator cal = (Calculator)obj; 로컬메소드호출방식으로사용 int value = 0; if(args[1].equals("+")) value = cal.sum(op1, op2); else if(args[1].equals("-")) value = cal.subtract(op1, op2); else if(args[1].equals("*")) value = cal.multiply(op1, op2); else if(args[1].equals("/")) value = cal.divide(op1, op2); 2009 Collaborative Computing Systems Lab, Konkuk Univ. 19 19
RMI 를이용한계산기애플리케이션 5) 스텁 / 스켈레톤생성 rmic CalculatorImpl 6) 원격객체를 rmiregistry 에등록 (server 디렉토리 ) Policy파일작성 rmiregistry 2000 ( 포트2000 에 registry실행 ) Java Djava.security.manager Djava.security.policy=policy CalculatorBind ( 등록 ) 7) 클라이언트실행 (client 디렉토리 ) Java CalculatorClient 정수연산자정수 2009 Collaborative Computing Systems Lab, Konkuk Univ. 20
RMI 를이용한채팅애플리케이션 로그인 대화 클라이언트가서버의 connect() 호출 서버는 connect() 가호출되면모든접속사용자에게로긴사용자정보를전달 클라이언트의 print() 원격메소드호출 서버도클라이언트측의원격메소드호출 (RMI 콜백 ) 클라이언트는별도의스레드로사용자입력처리 사용자입력문자열은서버의 broadcast() 호출하여다른클라이언트들에게전달 서버는 broadcast() 호출되면, 접속클라이언트들의 print() 원격메소드호출하여문자열내용전달 로그아웃 클라이언트는서버의 disconnect() 원격메소드호출 서버는접속클라이언트의 print() 호출하여로그아웃사용자정보전달 2009 Collaborative Computing Systems Lab, Konkuk Univ. 21
RMI-IIOP IIOP RMI 와코바의장점을결합한기업용전송기술 RMI 와코바의차이 코바 : IIOP 이용, RMI: JRMP 이용 코바 : 언어독립적, RMI: 자바에서만사용 코바 : 원격객체의위치찾기위해 CosNaming 이용, RMI: JNDI 이용 코바 : 객체직렬화기술사용안함, RMI: 객체직렬화기술사용 RMI-IIOP 의 RMI 개발과의차이 Rmiregistry 가아닌 tnameserv 실행 Rmic 실행시 iiop 옵션지정하여 iiop 형식의스텁과타이생성 원격객체는 PortableRemoteObject 상속 원격객체등록, 검색을위해 Connect 객체사용 Policy 파일필요없음 2009 Collaborative Computing Systems Lab, Konkuk Univ. 22
RMI-IIOP IIOP 예제 RMI-IIOP 를이용한 Hello 1) 원격인터페이스작성 2) 원격인터페이스를구현하는원격클래스작성 javax.rmi.portableremoteobject 상속 3) 원격객체를네이밍서버 (tnameserv) 에등록하는애플리케이션작성 4) 원격객체를이용하는클라이언트작성 5) 스텁과타이생성 (rmic 에 iiop 옵션지정 ) 6) 원격객체를네이밍서버 (tnameserv) 에등록 7) 클라이언트애플리케이션실행 2009 Collaborative Computing Systems Lab, Konkuk Univ. 23
RMI-IIOP IIOP 예제 1) 원격인터페이스작성 Java.rmi.Remote 인터페이스확장 메소드는모두 java.rmi.remoteexception throws 인자와반환값은모두직렬화가능형식 import java.rmi.remote; import java.rmi.remoteexception; public interface HelloIIOP extends Remote public String hello() throws RemoteException; 2009 Collaborative Computing Systems Lab, Konkuk Univ. 24 24
RMI-IIOP IIOP 예제 2) 원격인터페이스를구현하는원격클래스작성 Javax.rmi.PortableRemoteObject 상속 원격인터페이스의메소드구현 Java.rmi.RemoteException throws Java.rmi.RemoteException throws 하는기본생성자필요 import java.rmi.remoteexception; import javax.rmi.portableremoteobject; public class HelloIIOPImpl extends PortableRemoteObject implements HelloIIOP public HelloIIOPImpl() throws RemoteException public String hello() throws RemoteException return "Java World"; 2009 Collaborative Computing Systems Lab, Konkuk Univ. 25 25
RMI-IIOP IIOP 예제 3) 원격객체를네이밍서버 (tnameserv) 에등록하는애플리케이션작성 HelloIIOPImpl 객체등록 HelloIIOPImpl obj = new HelloIIOPImpl(); java.util.properties p = new java.util.properties(); p.put(context.initial_context_factory, "com.sun.jndi.cosnaming.cnctxfactory"); p.put(context.provider_url, "iiop://localhost"); Context ctx = new InitialContext(p); ctx.rebind("helloiiop", obj); Properties 객체에정보지정하여 InitialContext 생성자의인자로지정 InitialContext 는내부적으로 com.sun.jndi.cosnaming.cnctxfactory 클래스이용하여네이밍서버에접속 접속시 iiop 프로토콜사용하여 localhost 에접속 2009 Collaborative Computing Systems Lab, Konkuk Univ. 26
RMI-IIOP IIOP 예제 4) 원격객체를이용하는클라이언트작성 객체 lookup (Context 객체이용 ) java.util.properties p = new java.util.properties(); p.put(context.initial_context_factory, "com.sun.jndi.cosnaming.cnctxfactory"); p.put(context.provider_url, "iiop://localhost"); Context ctx = new InitialContext(p); Object obj = ctx.lookup("helloiiop"); HelloIIOP 인터페이스형변환 (PortableRemoteObject 의 narrow() 이용 ) HelloIIOP h = (HelloIIOP)PortableRemoteObject.narrow( obj,helloiiop.class); 원격객체호출 System.out.println(h.hello()); 2009 Collaborative Computing Systems Lab, Konkuk Univ. 27
RMI-IIOP IIOP 예제 5) 스텁과타이생성 Rmic iiop HelloIIOPImpl 6) 원격객체를네이밍서버 (tnameserv) 에등록 tnameserv 실행 원격객체등록 2009 Collaborative Computing Systems Lab, Konkuk Univ. 28
RMI-IIOP IIOP 예제 7) 클라이언트애플리케이션실행 2009 Collaborative Computing Systems Lab, Konkuk Univ. 29 29