Java RMI (Remote Method Invocation)을 알아보자
1. 개요
두 개의 JVM이 통신해야 할 때 Java RMI는 서로 소통할 수 있는 하나의 옵션입니다. 이 아티클에서는 Java RMI 기술을 보여주는 간단한 예시를 보도록 하겠습니다.
2. 서버 만들기
RMI 서버를 생성하는 데에는 필요한 단계는 두 가지가 있습니다.
- i) 클라이언트/서버 관계를 정의하는 인터페이스를 만듭니다.
- ii) 해당 인터페이스의 구현을 생성합니다.
RMI Java 애플리케이션을 작성하려면 아래 단계를 따라야합니다.
- 원격 인터페이스 정의 (Define the remote interface)
- 구현 클래스 (원격 객체) 개발 (Develop the implementation class
- 서버 프로그램 개발 (Server Implementation)
- 클라이언트 프로그램 개발 (Client Implementation)
- 애플리케이션 컴파일 (Application Compile)
- 응용 프로그램 실행 (Executing Application Program)
원격 인터페이스 정의
원격 인터페이스는 특정 원격 개체의 모든 메서드에 대한 설명을 제공합니다. 클라이언트는이 원격 인터페이스와 통신합니다.
원격 인터페이스를 생성하려면-
- 패키지에 속하는 미리 정의 된 인터페이스 Remote 를 확장하는 인터페이스를 만듭니다 .
- 이 인터페이스에서 클라이언트가 호출 할 수있는 모든 비즈니스 메소드를 선언하십시오.
- 원격 호출 중에 네트워크 문제 가 발생할 가능성이 있으므로 RemoteException 이라는 예외 가 발생할 수 있습니다. 던져.
다음은 원격 인터페이스의 예입니다. 여기에서 Hello 라는 이름의 인터페이스를 정의했으며 printMsg () 라는 메서드가 있습니다.
1
2
3
4
5
6
7
|
import java.rmi.Remote;
import java.rmi.RemoteException;
// Creating Remote interface for our application
public interface Hello extends Remote {
void printMsg() throws RemoteException;
}
|
cs |
구현 클래스 (원격 개체) 개발
이전 단계에서 만든 원격 인터페이스를 구현해야합니다. (구현 클래스를 별도로 작성하거나 서버 프로그램이이 인터페이스를 직접 구현하도록 만들 수 있습니다.)
구현 클래스를 개발하려면-
- 이전 단계에서 만든 인터페이스를 구현합니다.
- 원격 인터페이스의 모든 추상 메서드에 대한 구현을 제공합니다.
다음은 구현 클래스입니다. 여기에서는 ImplExample 이라는 클래스를 만들고 이전 단계에서 만든 Hello 인터페이스를 구현했으며 메시지를 인쇄하는이 메서드의 본문 을 제공했습니다 .
1
2
3
4
5
6
7
8
|
// Implementing the remote interface
public class ImplExample implements Hello {
// Implementing the interface method
public void printMsg() {
System.out.println("This is an example RMI program");
}
}
|
cs |
서버 프로그램 개발
RMI 서버 프로그램은 원격 인터페이스를 구현하거나 구현 클래스를 확장해야합니다. 여기에서 원격 객체를 생성하고이를 RMIregistry에 바인딩해야합니다 .
서버 프로그램을 개발하려면-
- 원격 개체를 호출하려는 위치에서 클라이언트 클래스를 만듭니다.
- 아래와 같이 구현 클래스를 인스턴스화하여 원격 개체 를 만듭니다 .
- java.rmi.server 패키지에 속하는 UnicastRemoteObject 라는 클래스의 exportObject () 메소드를 사용하여 원격 객체를 내 보냅니다 .
- 패키지 java.rmi.registry에 속하는 LocateRegistry 클래스 의 getRegistry () 메소드를 사용하여 RMI 레지스트리를 가져옵니다 .
- Registry 라는 클래스 의 bind () 메서드를 사용하여 생성 된 원격 객체를 레지스트리에 바인딩 합니다. 이 메서드에 바인딩 이름과 내 보낸 개체를 나타내는 문자열을 매개 변수로 전달합니다.
다음은 RMI 서버 프로그램의 예입니다.
public class Server extends ImplExample {
public Server() {}
public static void main(String args[]) {
try {
// Instantiating the implementation class
ImplExample obj = new ImplExample();
// Exporting the object of implementation class
// (here we are exporting the remote object to the stub)
Hello stub = (Hello) UnicastRemoteObject.exportObject(obj, 0);
// Binding the remote object (stub) in the registry
Registry registry = LocateRegistry.getRegistry();
registry.bind("Hello", stub);
System.err.println("Server ready");
} catch (Exception e) {
System.err.println("Server exception: " + e.toString());
e.printStackTrace();
}
}
}
|
cs |
클라이언트 프로그램 개발
클라이언트 프로그램을 작성하고 원격 개체를 가져와이 개체를 사용하여 필요한 메서드를 호출합니다.
클라이언트 프로그램을 개발하려면-
- 원격 개체를 호출하려는 위치에서 클라이언트 클래스를 만듭니다.
- 패키지 java.rmi.registry에 속하는 LocateRegistry 클래스 의 getRegistry () 메소드를 사용하여 RMI 레지스트리를 가져옵니다 .
- java.rmi.registry 패키지에 속하는 Registry 클래스의 lookup () 메소드를 사용하여 레지스트리에서 객체를 가져옵니다 .
- 이 메서드에는 바인딩 이름을 나타내는 문자열 값을 매개 변수로 전달해야합니다. 그러면 원격 개체가 반환됩니다.
- lookup ()은 remote 유형의 객체를 반환하고 Hello 유형으로 다운 캐스트합니다.
- 마지막으로 얻은 원격 개체를 사용하여 필요한 메서드를 호출합니다.
다음은 RMI 클라이언트 프로그램의 예입니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class Client {
private Client() {}
public static void main(String[] args) {
try {
// Getting the registry
Registry registry = LocateRegistry.getRegistry(null);
// Looking up the registry for the remote object
Hello stub = (Hello) registry.lookup("Hello");
// Calling the remote method using the obtained object
stub.printMsg();
// System.out.println("Remote method invoked");
} catch (Exception e) {
System.err.println("Client exception: " + e.toString());
e.printStackTrace();
}
}
}
|
cs |
응용 프로그램 컴파일
응용 프로그램을 컴파일하려면-
- 원격 인터페이스를 컴파일하십시오.
- 구현 클래스를 컴파일하십시오.
- 서버 프로그램을 컴파일하십시오.
- 클라이언트 프로그램을 컴파일하십시오.
또는,
모든 프로그램을 저장 한 폴더를 열고 아래와 같이 모든 Java 파일을 컴파일합니다.
javac *.java
응용 프로그램 실행
1 단계 - 다음 명령을 사용하여 rmi 레지스트리를 시작합니다 .
start rmiregistry
이렇게하면 아래와 같이 별도의 창에서 rmi 레지스트리 가 시작 됩니다.
2 단계 -아래와 같이 서버 클래스 파일을 실행합니다.
java Server
3 단계 -아래와 같이 클라이언트 클래스 파일을 실행합니다.
java Client
Verification- 클라이언트를 시작하자마자 서버에 다음 출력이 표시됩니다.
============================================================================
Example #01 : 예시 #01)
1
2
3
4
5
6
7
8
9
10
11
12
|
// RemoteDate.java
package RMIExample;
import java.util.Date;
import java.rmi.*;
public interface RemoteDate extends Remote
{
public abstract Date getDate() throws RemoteException;
}
|
cs |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
// RemoteDateImpl.java
package RMIExample;
import java.rmi.*;
import java.rmi.server.UnicastRemoteObject;
import java.util.Date;
public class RemoteDateImpl extends UnicastRemoteObject implements RemoteDate
{
public RemoteDateImpl() throws RemoteException { }
public Date getDate() throws RemoteException {
return new Date();
}
public static void main(String[] args) {
try {
RemoteDate dateServer = new RemoteDateImpl();
Naming.rebind("DateServer", dateServer);
System.out.println("DateServer bound in registry");
}
catch (Exception e) {
System.err.println(e);
}
}
}
|
cs |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
// RMIClient.java
package RMIExample;
import java.rmi.*;
public class RMIClient
{
public static void main(String args[]) {
try {
String host = "rmi://127.0.0.1/DateServer";
RemoteDate dateServer = (RemoteDate)Naming.lookup(host);
System.out.println(dateServer.getDate());
}
catch (Exception e) {
System.err.println(e);
}
}
}
|
cs |
============================================================================
RMI 프로그램을 작성하는 6 단계가 제공됩니다.
- 원격 인터페이스 만들기
- 원격 인터페이스 구현 제공
- 구현 클래스를 컴파일하고 rmic 도구를 사용하여 스텁 및 스켈레톤 객체를 만듭니다.
- rmiregistry 도구로 레지스트리 서비스 시작
- 원격 애플리케이션 생성 및 시작
- 클라이언트 응용 프로그램 만들기 및 시작
RMI 예
이 예에서는 6 단계를 모두 수행하여 rmi 애플리케이션을 만들고 실행했습니다. 클라이언트 응용 프로그램에는 원격 인터페이스와 클라이언트 응용 프로그램의 두 파일 만 필요합니다. rmi 애플리케이션에서 클라이언트와 서버는 모두 원격 인터페이스와 상호 작용합니다. 클라이언트 응용 프로그램은 프록시 개체에서 메서드를 호출하고 RMI는 원격 JVM에 요청을 보냅니다. 반환 값은 프록시 개체로 다시 전송 된 다음 클라이언트 응용 프로그램으로 전송됩니다.
원격 인터페이스를 만들려면 원격 인터페이스를 확장하고 원격 인터페이스의 모든 메서드를 사용하여 RemoteException을 선언합니다. 여기서는 원격 인터페이스를 확장하는 원격 인터페이스를 생성합니다. add ()라는 메서드는 하나 뿐이며 RemoteException을 선언합니다.
1
2
3
4
5
|
import java.rmi.*;
public interface Adder extends Remote {
public int add(int x,int y) throws RemoteException;
}
|
cs |
2) 원격 인터페이스 구현 제공
이제 원격 인터페이스의 구현을 제공하십시오. 원격 인터페이스 구현을 제공하려면 다음을 수행해야합니다.
- UnicastRemoteObject 클래스를 확장하거나
- 또는 UnicastRemoteObject 클래스의 exportObject () 메서드를 사용하십시오.
UnicastRemoteObject 클래스를 확장하는 경우 RemoteException을 선언하는 생성자를 정의해야합니다.
1
2
3
4
5
6
7
8
9
10
|
import java.rmi.*;
import java.rmi.server.*;
public class AdderRemote extends UnicastRemoteObject implements Adder {
AdderRemote() throws RemoteException{
super();
}
public int add(int x,int y) { return x + y; }
}
|
cs |
3) rmic 도구를 사용하여 스텁 및 스켈레톤 개체를 만듭니다.
다음 단계는 rmi 컴파일러를 사용하여 스텁 및 스켈레톤 객체를 만드는 것입니다. rmic 도구는 RMI 컴파일러를 호출하고 스텁 및 스켈레톤 객체를 생성합니다.
rmic AdderRemote
4) rmiregistry 도구로 레지스트리 서비스 시작
이제 rmiregistry 도구를 사용하여 레지스트리 서비스를 시작하십시오. 포트 번호를 지정하지 않으면 기본 포트 번호가 사용됩니다. 이 예에서는 포트 번호 5000을 사용합니다.
rmiregistry 5000
5) 서버 애플리케이션 생성 및 실행
이제 rmi 서비스는 서버 프로세스에서 호스팅되어야합니다. Naming 클래스는 원격 개체를 가져오고 저장하는 메서드를 제공합니다. Naming 클래스는 5 가지 메서드를 제공합니다.
public static java.rmi.Remote lookup(java.lang.String) throws java.rmi.NotBoundException, java.net.MalformedURLException, java.rmi.RemoteException; | It returns the reference of the remote object. |
public static void bind(java.lang.String, java.rmi.Remote) throws java.rmi.AlreadyBoundException, java.net.MalformedURLException, java.rmi.RemoteException; | It binds the remote object with the given name. |
public static void unbind(java.lang.String) throws java.rmi.RemoteException, java.rmi.NotBoundException, java.net.MalformedURLException; | It destroys the remote object which is bound with the given name. |
public static void rebind(java.lang.String, java.rmi.Remote) throws java.rmi.RemoteException, java.net.MalformedURLException; | It binds the remote object to the new name. |
public static java.lang.String[] list(java.lang.String) throws java.rmi.RemoteException, java.net.MalformedURLException; | It returns an array of the names of the remote objects bound in the registry. |
1
2
3
4
5
6
7
8
9
10
11
|
import java.rmi.*;
import java.rmi.registry.*;
public class MyServer{
public static void main(String args[]){
try {
Adder stub = new AdderRemote();
Naming.rebind("rmi://localhost:5000/sonoo",stub);
} catch(Exception e) { System.out.println(e); }
}
}
|
cs |
6) 클라이언트 애플리케이션 생성 및 실행
클라이언트에서 우리는 Naming 클래스의 lookup () 메소드에 의해 stub 객체를 얻고이 객체에 대한 메소드를 호출합니다. 이 예에서는 동일한 시스템에서 서버 및 클라이언트 응용 프로그램을 실행하므로 localhost를 사용하고 있습니다. 다른 시스템에서 원격 개체에 액세스하려면 로컬 호스트를 원격 개체가있는 호스트 이름 (또는 IP 주소)으로 변경합니다.
1
2
3
4
5
6
7
8
9
10
|
import java.rmi.*;
public class MyClient{
public static void main(String args[]){
try{
Adder stub = (Adder)Naming.lookup("rmi://localhost:5000/sonoo");
System.out.println(stub.add(34,4));
}catch (Exception e) { }
}
}
|
cs |
실행
1) javac *.java
2) rmic AdderRemote
3) rmiregistry 5000
4) java MyServer
5) java MyClient
'공부 > Object-Oriented Design Pattern' 카테고리의 다른 글
Java RMI (Remote Method Invocation) (3) (1) | 2021.04.03 |
---|---|
Java RMI (Remote Method Invocation) (2) (0) | 2021.04.03 |
[OODP] Singleton Pattern (싱글톤 패턴) (0) | 2021.04.01 |
[OODP] Strategy Pattern (전략 패턴) (0) | 2021.03.28 |
[어댑터 패턴] Class Adaptor vs. Object Adaptor (0) | 2021.03.27 |
댓글