160 likes | 328 Views
(분산 통신 실습) RMI. RMI 익히기 분산환경에서 동작하는 message-passing 을 이용한 bounded-buffer 해법 프로그램을 실행해 보세요. 소스 코드: ftp://117.16.244.157 -> os -> OSJavaSources -> ch15 -> rmi http :// marvel.incheon.ac.kr 의 Information Unix RMI 참조
E N D
(분산 통신 실습) RMI • RMI 익히기 • 분산환경에서 동작하는 message-passing을 이용한 bounded-buffer 해법 프로그램을 실행해 보세요. • 소스 코드: ftp://117.16.244.157 -> os -> OSJavaSources -> ch15 -> rmi • http://marvel.incheon.ac.kr의 InformationUnix RMI참조 • 또, 이 예제가 웹 상에서 수행될 수 있도록 수정해 보세요. 즉 클라이언트 프로그램에서 이 예제의 Producer와 Consumer의 동작을 모니터링하는 Java applet을 작성해 보는 것입니다. • AppletViewer 또는 넷스케이프 커뮤니케이터로 실행 • 실습방법 • multi.incheon.ac.kr(117.16.244.157)의 숙제방에 소스 프로그램과 실행 파일을 옮겨놓으세요. • 서버 프로그램 MessageQueueImpl 은 multi 에 실행하고, 클라이언트 프로그램 Factory 는 윈도우 컴퓨터 에서 실행해보세요. • (Linux 에서 컴파일오류 디버깅)
RMI (Remote Method Invocation) • RPC의 Java 버전 • 저수준(low-level) 소켓을 이용하지 않고 원격 객체의 메소드를 호출할 수 있는 방법을 제공하는 객체 지향 언어인 Java 기반의 분산 컴퓨팅 환경(클라이언트/서버 지원)을 위한 미들웨어(RPC와 유사) • 스레드(thread)가 원격 객체(Remote Object)의 메소드(method) 호출 • 다른 Java Virtual Machine 상에 있는 객체는 “원격” 객체 • RPC 보다 좋은점 • 객체 지향적이다. • 프로그램 작성 및 사용이 쉽다. • 안전하고 보안성이 있다. • 기존 시스템과 통합해서 사용할 수 있다. • 작성 절차 • 원격 인터페이스를 정의한다. • 원격 인터페이스를 구현(implement)하는 원격객체(서버)를 작성한다. • 원격 객체를 이용하는 프로그램(클라이언트)을 작성한다. • stub와 skeleton 클래스를 생성한다. • rmiregistry를 실행시킨다. • 서버와 클라이언트를 실행시킨다.
RMI (Remote Method Invocation) • RPC versus RMI • RPC : Procedural Programming Style • RMI : Object-Oriented Programming Style • RPC의 매개변수 : Ordinary Data Structures • RMI의 매개변수 : Objects • Stubs and Skeletons • “Stub” • 클라이언트에 상주하는 원격 객체의 대리인(proxy) • 매개변수들을 “Marshalls”(메소드 이름과 인자들의 꾸러미 생성)해서 서버로 보냄 • “Skeleton” • 서버에 상주 • 매개변수를 “Unmarshalls”해서 서버에 전달함 • 매개변수 • Marshall된 매개변수가 Local (Non-Remote) Objects이면 객체를 바이트 스트림으로 기록해 주는 객체 순서화(Object Serialization) 기법을 이용해서 복사에 의해(by Value) 전달 • Marshall 된 매개변수가 Remote Objects이면 참조에 의해(by Reference) 전달 : RMI의 장점 • Remote objects • java.rmi.Remote를 확장한 Interface로 선언되어야 함 …extends java.rmi.Remote • 모든 메소드는 java.rmi.RemoteException을 발생시켜야 함 … throws java.rmi.RemoteException
RMI 프로그램 예제 원격 인터페이스 구현 server MessageQueueImpl.java MessageQueueImpl.class javac MessageQueue.java MessageQueueImpl_skel.class rmic MessageQueueImpl_stub.class Factory.java Producer.java javac Factory.class Consumer.java client
RMI 프로그램 예제 • 구성 • 원격 인터페이스: MessageQueue.java • 서버 프로그램: MessageQueueImpl.java • 클라이언트 프로그램: Factory.java, Producer.java, Consumer.java • Policy File : New with Java 2 grant { permission java.net.SocketPermission "*:1024-65535","connect,accept"; };
RMI 프로그램 예제 • 실행 순서 • 모든 소스 파일 컴파일 $ javac MessageQueue.java MessageQueueImpl.java Factory.java Producer.java Consumer.java • rmic로 stub와 skeleton class 파일 생성 $ rmic MessageQueueImpl • 레지스트리 서비스 시작 (rmiregistry) … osagent 또는 rpcbind 디몬에 해당 $ rmiregistry & (Unix & Linux) 또는 C:\> start rmiregistry (Windows) • 원격 서버 객체의 인스턴스 생성 (JDK 1.2 이상 버전에서는 인증해 주어야 함) $ java -Djava.security.policy=java.policy MessageQueueImpl (JDK 1.2 이상) 또는 $ java MessgeQueueImpl (JDK 1.1) • 클라이언트에서 원격 객체 실행 시작 $ java -Djava.security.policy=java.policy Factory (JDK .2 이상) 또는 $ java Factory (JDK 1.1)
RMI 프로그램 예제 • 서버 : MessageQueue interface import java.util.*; import java.rmi.*; public interface MessageQueue extends java.rmi.Remote { /* * This implements a non-blocking send */ public void send(Object item) throws java.rmi.RemoteException; /* * This implements a non-blocking receive */ public Object receive() throws java.rmi.RemoteException; }
RMI 프로그램 예제 • 서버 : MessageQueueImpl.java (1) import java.util.*; import java.rmi.*; public class MessageQueueImpl extends java.rmi.server.UnicastRemoteObject implements MessageQueue { public MessageQueueImpl() throws RemoteException { queue = new Vector(); } // This implements a non-blocking send public synchronized void send(Object item) throws RemoteException { queue.addElement(item); System.out.println("Producer entered " + item + " size = " + queue.size()); }
RMI 프로그램 예제 • 서버 : MessageQueueImpl.java (2) // This implements a non-blocking receive public synchronized Object receive() throws RemoteException { Object item; if (queue.size() == 0) return null; else { item = queue.firstElement(); queue.removeElementAt(0); System.out.println("Consumer removed " + item + " size = " + queue.size()); return item; } }
RMI 프로그램 예제 • 서버 : MessageQueueImpl.java (3) public static void main(String args[]) { System.setSecurityManager(new RMISecurityManager()); try { MessageQueue server = new MessageQueueImpl(); Naming.rebind("//127.0.0.1/MessageServer", server); //Naming.rebind("rmi://media.inchon.ac.kr/MessageServer", server); System.out.println("Server Bound"); } catch(Exception e) { System.err.println(e); } } private Vector queue; }
RMI 프로그램 예제 • 클라이언트 : Factory.java (1) import java.util.*; import java.rmi.*; public class Factory { public Factory() { // remote object MessageQueue mailBox; System.setSecurityManager(new RMISecurityManager()); // install a security manager try { //get a reference to the remote object mailBox = (MessageQueue)Naming.lookup(“//127.0.0.1/MessageServer"); //(MessageQueue)Naming.lookup("rmi://media.inchon.ac.kr/MessageServer"); // now create the producer and consumer threads Producer producerThread = new Producer(mailBox); Consumer consumerThread = new Consumer(mailBox); producerThread.start(); consumerThread.start(); } catch (Exception e) { System.err.println(e); } }
RMI 프로그램 예제 • 클라이언트 : Factory.java (2) // producer and consumer will call this to nap public static void napping() { int sleepTime = (int) (NAP_TIME * Math.random() ); try { Thread.sleep(sleepTime*1000); } catch(InterruptedException e) { } } public static void main(String args[]) { Factory client = new Factory(); } private static final int NAP_TIME = 5; }
RMI 프로그램 예제 • 클라이언트 : Producer.java import java.util.*; class Producer extends Thread{ public Producer(MessageQueue m) { mbox = m; } public void run() { Date message; while (true) { Factory.napping(); // produce an item & enter it into the buffer message = new Date(); try { mbox.send(message); System.out.println(“Producer Produced ” + message); } catch (Exception e) { System.err.println(e); } } } private MessageQueue mbox; }
RMI 프로그램 예제 • 클라이언트 : Consumer.java import java.util.*; class Consumer extends Thread { public Consumer(MessageQueue m) { mbox = m; } public void run() { Date message; while (true) { Factory.napping(); // consume an item from the buffer try { message = (Date)mbox.receive(); if (message != null) // Consume the item System.out.println(“Consumer Consumed ” + message); } catch (Exception e) { System.err.println(e); } } } private MessageQueue mbox; }