▣ RMI(Remote Method Invocation)
- 분산 시스템 구축시 Socket 방식을 이용하는 것보다 간결하고 신속함
- RPC(Remote Procedure Call) : 원격지의 함수 호출, C 언어에서 사용
- CORBA의 분산 객체 시스템과 비슷(이기종 간의 분산 처리 구축, 코바서버를 2중으로 구축시 모든 서버에서 트랜잭션이 안정적으로 진행이 안됨)
- 원리
Client Area ↓ ↓Server Area
-----------------------------------------------------------------------------------------
Local System --> Class --> Stub --> NETWORK --> Stub --> Skeleton --> Class Remote System
결과전송 <-- Stub <-- NETWORK <----------- Skeleton <-- 비지니스 로직 처리
1. RMI 프로그래밍 순서도
① 원격 인터페이스 정의
② 원격 객체 구현
③ javac 컴파일 - 원격 객체 클래스
④ rmic - Stub, Skeleton class 생성
⑤ 로컬 객체 클래스 제작
⑤ RMI 등록 서버 실행
⑥ 클라이언트 접속
2. UnicastRemoteObject 의 상속 구조
public abstract class RemoteObject extends Object implements Remote, Serializable
--> java.lang.Object 클래스의 hashCode(), equals(), toString() 메소드를 구현해서 갖고 있는 클래스
↑
public abstract class RemoteServer extends RemoteObject
--> 원격지 메소드 참조에 대한 구현에 대한 FrameWork을 갖고 있는 최상위 클래스
↑
public class UnicastRemoteObject extends RemoteServer
--> tcp 상에서 object reference를 참조할 수 있도록 지원해 주는 클래스
3. Echo 예제 실습
--------------------------------------------------------------------------
구분 CLIENT SIDE SERVER SIDE
--------------------------------------------------------------------------
Interface Echo.class Echo.class
Remote Object EchoImpl.class
Proxy EchoImpl_Stub.class EchoImpl_Stub/Skel.class
Run Class EchoClient.class EchoServer.class
--------------------------------------------------------------------------
실행 순서
1. rmic EchoImp
2. start rmiregistry <-- C:\Program Files\Oracle\jre\1.1.7\bin; 경로가 PATH에 있으면 제거하고 시스템 재 시작합니다.
3. java EchoServer
4. java EchoClient nulunggi
------------------------ e.bat ------------------------
rmic EchoImpl
start rmiregistry
rem ---------
rem 서버 작동
rem ---------
java EchoServer
1/4-------------------------- Echo.java --------------------------
import java.rmi.RemoteException;
import java.rmi.Remote;
public interface Echo extends Remote{
public String sayEcho(String name) throws RemoteException;
}
2/4-------------------------- EchoImpl.java --------------------------
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
public class EchoImpl extends UnicastRemoteObject implements Echo{
String message;
public EchoImpl() throws RemoteException{}
public EchoImpl(String message) throws RemoteException{
this.message = message;
}
public String sayEcho(String name){
return "\n 엄기흥 강사 PC 로 부터 전송된 문자열 : " + message + " " + name + "님 \n";
}
}
3/4-------------------------- EchoServer.java --------------------------
import java.rmi.Naming;
public class EchoServer{
public static void main(String args[]){
try{
EchoImpl echoRef = new EchoImpl();
Naming.bind("Echo",echoRef);
}catch( java.rmi.AlreadyBoundException e){
e.printStackTrace();
}catch(java.net.MalformedURLException e ){
e.printStackTrace();
}catch( java.rmi.RemoteException e){
e.printStackTrace();
}
System.out.println("--------------------------------");
System.out.println("Echo RMI 서버가 작동 되었습니다.");
System.out.println("--------------------------------");
}
}
4/4-------------------------- EchoClient.java --------------------------
import java.rmi.Naming;
import java.rmi.*;
import java.net.*;
public class EchoClient{
public static void main(String args[]){
String url = "rmi://127.0.0.1/Echo";
//String url = "rmi://" + args[0] + "/Echo";
Echo echoRef = null;
try{
echoRef = (Echo)Naming.lookup(url);
System.out.println(echoRef.sayEcho(args[0]));
}catch(RemoteException e){
e.printStackTrace();
}catch(MalformedURLException e){
e.printStackTrace();
}catch(NotBoundException e){
e.printStackTrace();
}
}
}
4. RMI 서버 모듈의 분리 예제
--------------------------------------------------------------------------
구분 CLIENT SIDE SERVER SIDE
--------------------------------------------------------------------------
Interface Echo.class Echo.class
EchoFactory.class EchoFactory.class
Remote Object EchoImpl.class
EchoFactoryImpl.class
Proxy EchoImpl_Stub.class EchoImpl_Stub/Skel.class
EchoFactoryImpl_Stub.class EchoFactoryImpl_Stub/Skel.class
Run Class EchoFactoryClient.class EchoFactoryServer.class
Start File s.bat r.bat
--------------------------------------------------------------------------
실행 방법 : r.bat
rem ---------------------------------------
rem 파일 내용 : Echo 예제 배치파일 입니다.
rem 작성일 : 2002-01-01
rem 작성자 : 엄기흥
rem ---------------------------------------
rmic EchoImpl
rmic EchoFactoryImpl
start rmiregistry.exe
java EchoFactoryServer
1/6------------------------ Echo.java ------------------------
import java.rmi.RemoteException;
import java.rmi.Remote;
public interface Echo extends Remote{
public String sayEcho(String name) throws RemoteException;
}
2/6------------------------ EchoImpl.java ------------------------
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
public class EchoImpl extends UnicastRemoteObject implements Echo{
String message;
public EchoImpl() throws RemoteException{}
public EchoImpl(String message) throws RemoteException{
this.message = message;
}
public String sayEcho(String name){
return "\n " + message + " " + name + "님 \n";
}
}
3/6------------------------ EchoFactory.java ------------------------
import java.rmi.RemoteException;
import java.rmi.Remote;
public interface EchoFactory extends Remote{
public Echo getEcho(String greeting) throws RemoteException;
}
4/6------------------------ EchoFactoryImpl.java ------------------------
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
public class EchoFactoryImpl extends UnicastRemoteObject implements EchoFactory{
public EchoFactoryImpl() throws RemoteException{}
public Echo getEcho(String message) throws RemoteException{
EchoImpl echoRef = new EchoImpl(message);
return (Echo)echoRef;
}
}
5/6------------------------ EchoFactoryServer.java ------------------------
import java.rmi.Naming;
public class EchoFactoryServer {
public static void main(String args[]) throws Exception{
EchoFactoryImpl factoryRef = new EchoFactoryImpl();
Naming.rebind("EchoFactory",factoryRef);
System.out.println("서버가 시작되었습니다.");
}
}
6/6------------------------ EchoFactoryClient.java ------------------------
import java.rmi.Naming;
import java.rmi.*;
import java.net.*;
public class EchoFactoryClient{
public static void main(String args[]){
//String url = "rmi://127.0.0.1/EchoFactory";
EchoFactory ref = null;
try{
if (args.length != 2){
System.out.println("파라미터가 잘못되었습니다.");
System.out.println("사용법 : java EchoFactoryClient nulunggi 211.108.242.114");
System.exit(1);
}
ref = (EchoFactory)Naming.lookup("rmi://" + args[1] + "/EchoFactory");
Echo echoHello = ref.getEcho("수고하셨습니다.");
Echo echoGood = ref.getEcho("2개월간 고생하셨습니다.");
System.out.println(echoHello.sayEcho(args[0]));
System.out.println(echoGood.sayEcho(args[0]));
}catch(RemoteException e){
e.printStackTrace();
}catch(MalformedURLException e){
e.printStackTrace();
}catch(NotBoundException e){
e.printStackTrace();
}
}
}
▣ RMI + Thread를 이용하여 여러 컴퓨터에서 계산하기
------------------------ e.bat ------------------------
rmic EchoImpl
start rmiregistry
rem ---------
rem 서버 작동
rem ---------
java EchoServer
1. 서버쪽 수정 EchoImpl.java
1/4-------------------------- Echo.java --------------------------
import java.rmi.RemoteException;
import java.rmi.Remote;
public interface Echo extends Remote{
public String sayEcho(String name) throws RemoteException;
}
2/4-------------------------- EchoImpl.java --------------------------
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
public class EchoImpl extends UnicastRemoteObject implements Echo{
String message;
public EchoImpl() throws RemoteException{}
public EchoImpl(String message) throws RemoteException{
this.message = message;
}
public String sayEcho(String name){
int i=1;
long hap=0;
for(long q=1; q<=500000000; q++){
hap = hap + q;
}
return i + "번째 1부터 500,000,000까지의 합 : " + hap + "\n";
}
}
3/4-------------------------- EchoServer.java --------------------------
import java.rmi.Naming;
public class EchoServer{
public static void main(String args[]){
try{
EchoImpl echoRef = new EchoImpl();
Naming.bind("Echo",echoRef);
}catch( java.rmi.AlreadyBoundException e){
e.printStackTrace();
}catch(java.net.MalformedURLException e ){
e.printStackTrace();
}catch( java.rmi.RemoteException e){
e.printStackTrace();
}
System.out.println("--------------------------------");
System.out.println("Thread용 Echo RMI 서버가 작동 되었습니다.");
System.out.println("--------------------------------");
}
}
4/4-------------------------- EchoClient.java --------------------------
import java.rmi.Naming;
import java.rmi.*;
import java.net.*;
public class EchoClient{
public static void main(String args[]){
String url = "rmi://127.0.0.1/Echo";
//String url = "rmi://" + args[0] + "/Echo";
Echo echoRef = null;
try{
echoRef = (Echo)Naming.lookup(url);
System.out.println(echoRef.sayEcho(args[0]));
}catch(RemoteException e){
e.printStackTrace();
}catch(MalformedURLException e){
e.printStackTrace();
}catch(NotBoundException e){
e.printStackTrace();
}
}
}
2. 클라이언트쪽
------------------------ EchoClientThread.java -------------------
/***********************************
파일명:
작성자: 엄기흥
최종 수정일: 20020308-2102
파일 내용: 자바 수업 중에 테스트 한 파일
************************************/
import java.rmi.Naming;
import java.rmi.*;
import java.net.*;
public class EchoClientThread extends Thread{
String ip=null;
Echo echoRef = null;
EchoClientThread(String ip){
this.ip = ip;
}
public void run(){
try{
String url = "rmi://" + ip + "/Echo";
echoRef = (Echo)Naming.lookup(url);
System.out.println(echoRef.sayEcho("누룽지"));
}catch(RemoteException e){
e.printStackTrace();
}catch(MalformedURLException e){
e.printStackTrace();
}catch(NotBoundException e){
e.printStackTrace();
}
}
public static void main(String args[]){
EchoClientThread e67, e74, e76, e78, e98, e72, e69;
e67 = new EchoClientThread("211.108.242.106");
e74 = new EchoClientThread("211.108.242.107");
e76 = new EchoClientThread("211.108.242.109");
e78 = new EchoClientThread("211.108.242.110");
e98 = new EchoClientThread("211.108.242.108");
e72 = new EchoClientThread("211.108.242.112");
e69 = new EchoClientThread("211.108.242.114");
e67.start();
e74.start();
e76.start();
e78.start();
e98.start();
e72.start();
e69.start();
}
}
------------------------ EchoClientThread1.java -------------------
/***********************************
파일명:
작성자: 엄기흥
최종 수정일: 20020308-2102
파일 내용: 자바 수업 중에 테스트 한 파일
************************************/
import java.rmi.Naming;
import java.rmi.*;
import java.net.*;
public class EchoClientThread1 extends Thread{
String ip=null;
Echo echoRef = null;
EchoClientThread1(String ip){
this.ip = ip;
}
public void run(){
try{
if(ip.equals("67")){
String url = "rmi://211.108.242.114/Echo";
echoRef = (Echo)Naming.lookup(url);
System.out.println(echoRef.sayEcho("누룽지"));
}else if(ip.equals("74")){
String url = "rmi://211.108.242.106/Echo";
echoRef = (Echo)Naming.lookup(url);
System.out.println(echoRef.sayEcho("누룽지"));
}else if(ip.equals("76")){
String url = "rmi://211.108.242.107/Echo";
echoRef = (Echo)Naming.lookup(url);
System.out.println(echoRef.sayEcho("누룽지"));
}else if(ip.equals("78")){
String url = "rmi://211.108.242.109/Echo";
echoRef = (Echo)Naming.lookup(url);
System.out.println(echoRef.sayEcho("누룽지"));
}else if(ip.equals("98")){
String url = "rmi://211.108.242.110/Echo";
echoRef = (Echo)Naming.lookup(url);
System.out.println(echoRef.sayEcho("누룽지"));
}else if(ip.equals("72")){
String url = "rmi://211.108.242.111/Echo";
echoRef = (Echo)Naming.lookup(url);
System.out.println(echoRef.sayEcho("누룽지"));
}else if(ip.equals("69")){
String url = "rmi://211.108.242.112/Echo";
echoRef = (Echo)Naming.lookup(url);
System.out.println(echoRef.sayEcho("누룽지"));
}
}catch(RemoteException e){
e.printStackTrace();
}catch(MalformedURLException e){
e.printStackTrace();
}catch(NotBoundException e){
e.printStackTrace();
}
}
public static void main(String args[]){
EchoClientThread1 e67, e74, e76, e78, e98, e72, e69;
e67 = new EchoClientThread1("67");
e74 = new EchoClientThread1("74");
e76 = new EchoClientThread1("76");
e78 = new EchoClientThread1("78");
e98 = new EchoClientThread1("98");
e72 = new EchoClientThread1("72");
e69 = new EchoClientThread1("69");
e67.start();
e74.start();
e76.start();
e78.start();
e98.start();
e72.start();
e69.start();
}
}