JavaRush /Java Blog /Random-KO /RMI: 사용 실습

RMI: 사용 실습

Random-KO 그룹에 게시되었습니다
안녕하세요! 오늘 우리는 다소 흥미로운 주제인 RMI를 살펴보겠습니다 . 이는 원격 메소드 호출(Remote Method Invocation)을 의미합니다 . RMI: 사용 사례 - 1RMI를 사용하면 두 프로그램이 서로 다른 컴퓨터에 있더라도 서로 통신하도록 가르칠 수 있습니다. 멋진데? :) 하지만 그렇게 어렵지는 않습니다! 오늘 강의에서는 RMI 상호작용이 어떤 부분으로 구성되어 있는지, 어떻게 구성하는지 알아보겠습니다. 가장 먼저 필요한 것은 클라이언트서버 입니다 . 컴퓨터 용어에 너무 깊이 들어갈 필요는 없습니다. RMI의 경우 이는 단순히 두 개의 프로그램입니다. 그 중 하나는 일부 개체를 포함하고 두 번째는 이 개체의 메서드를 호출합니다. 한 프로그램에서 다른 프로그램에 있는 객체의 메소드를 호출하는 것 – 이전에는 이런 일을 해본 적이 없습니다! 이제 시도해 볼 시간입니다! :) 야생에서 익사하지 않으려면 프로그램을 단순하게 만드세요. 일반적으로 서버는 일반적으로 클라이언트가 요청하는 일종의 계산을 수행합니다. 우리도 마찬가지일 것입니다. 우리는 간단한 계산기 프로그램을 서버로 사용할 것입니다. 그녀는 오직 한 가지 방법만을 갖게 될 것입니다 - multiply(). 클라이언트 프로그램이 보낸 두 숫자를 곱하고 결과를 반환합니다. 우선 인터페이스가 필요합니다.
import java.rmi.Remote;
import java.rmi.RemoteException;

public interface Calculator extends Remote {

   int multiply(int x, int y) throws RemoteException;
}
인터페이스가 왜 필요한가요? 사실 RMI의 작업은 이전 강의 중 하나에서 공부한 프록시 생성을 기반으로 합니다 . 그리고 아마 기억하시겠지만 프록시를 사용한 작업은 클래스가 아닌 인터페이스 수준에서 정확하게 수행됩니다. 우리 인터페이스에는 두 가지 중요한 요구 사항이 있습니다!
  1. 원격 토큰 인터페이스를 상속해야 합니다.
  2. 모든 메소드는 RemoteException을 발생시켜야 합니다(IDE에서는 자동으로 수행되지 않으므로 수동으로 작성해야 합니다!).
이제 인터페이스를 구현할 서버 클래스를 생성해야 합니다 Calculator. RMI: 사용 실습 - 2여기의 모든 것도 매우 간단합니다.
import java.rmi.RemoteException;

public class RemoteCalculationServer implements Calculator {

   @Override
   public int multiply(int x, int y) throws RemoteException {
       return x*y;
   }

}
여기에는 코멘트할 내용이 많지 않습니다 :) 이제 서버 계산기 클래스를 구성하고 실행하는 서버 프로그램을 작성해야 합니다. 다음과 같이 보일 것입니다:
import java.rmi.AlreadyBoundException;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;

public class ServerMain {

   public static final String UNIQUE_BINDING_NAME = "server.calculator";

   public static void main(String[] args) throws RemoteException, AlreadyBoundException, InterruptedException {

       final RemoteCalculationServer server = new RemoteCalculationServer();

       final Registry registry = LocateRegistry.createRegistry(2732);

       Remote stub = UnicastRemoteObject.exportObject(server, 0);
       registry.bind(UNIQUE_BINDING_NAME, stub);

       Thread.sleep(Integer.MAX_VALUE);

   }
}
알아봅시다 :) 첫 번째 줄에서는 일종의 문자열 변수를 만듭니다.
public static final String UNIQUE_BINDING_NAME = "server.calculator";
이 문자열은 원격 개체의 고유 이름 입니다 . 이 이름으로 클라이언트 프로그램은 우리 서버를 찾을 수 있습니다. 나중에 이를 보게 될 것입니다. 다음으로 계산기 개체를 만듭니다.
final RemoteCalculationServer server = new RemoteCalculationServer();
여기에서는 모든 것이 명확합니다. 다음은 더 흥미롭습니다.
final Registry registry = LocateRegistry.createRegistry(2732);
레지스트리라고 불리는 것은 삭제된 개체의 레지스트리 입니다 . "삭제"는 컴퓨터에서 삭제했다는 의미가 아니라 이 레지스터의 개체에 다른 프로그램에서 원격으로 액세스할 수 있다는 의미입니다. :) LocateRegistry.createRegistry()번호 2732를 메서드에 전달했습니다. 이것이 포트 번호입니다. 포트가 무엇인지 모르는 경우 여기에서 읽을 수 있습니다 . 그러나 지금은 이것이 다른 프로그램이 개체 레지스트리를 찾을 수 있는 고유 번호라는 점만 기억하면 됩니다(아래에서도 볼 수 있음). 계속 진행합시다. 다음 줄에서 무슨 일이 일어나는지 봅시다:
Remote stub = UnicastRemoteObject.exportObject(server, 0);
이 줄에서 우리는 stub을 생성합니다 . 스텁은 전체 원격 호출 프로세스를 자체적으로 캡슐화합니다. 이것이 RMI의 가장 중요한 요소 라고 할 수 있다 . 그녀가 무엇을하고 있니?
  1. 메소드에 대한 원격 호출에 대한 모든 정보를 수신합니다.
  2. 메서드에 매개변수가 있는 경우 스텁은 해당 매개변수를 역직렬화합니다. 이 점을 주목하세요! 원격 호출을 위해 메소드에 전달하는 매개변수는 직렬화 가능해야 합니다(결국 네트워크를 통해 전송됩니다). 그런 문제는 없습니다. 단지 숫자만 전송하면 됩니다. 하지만 객체를 전송하는 경우에는 이를 잊지 마세요!
  3. 그런 다음 원하는 메서드를 호출합니다.
UnicastRemoteObject.exportObject()서버 계산기 개체를 메서드에 전달합니다 . 이렇게 하면 해당 메서드를 원격으로 호출할 수 있습니다. 이제 우리가 해야 할 일은 한 가지뿐입니다.
registry.bind(UNIQUE_BINDING_NAME, stub);
우리는 맨 처음에 생각해낸 이름으로 원격 개체 레지스트리에 스텁을 "등록"합니다. 이제 클라이언트가 그것을 찾을 수 있습니다! 마지막에 프로그램의 메인 스레드를 절전 모드로 전환한 것을 눈치챘을 것입니다.
Thread.sleep(Integer.MAX_VALUE);
우리는 서버를 오랫동안 계속 운영하기만 하면 됩니다. 우리는 IDEa에서 두 가지 메서드를 동시에 실행할 것입니다 . 먼저 서버 메서드( 이미 작성한 main()클래스에 있음 )와 클라이언트 메서드( 아래에 작성할 클래스에 있음)입니다. 클라이언트를 실행하는 동안 서버 프로그램이 다운되지 않는 것이 중요하므로 간단히 오랫동안 절전 모드로 설정합니다. 여전히 작동합니다. :) 이제 서버 메서드를 실행할 수 있습니다. 실행하고 클라이언트 프로그램이 메소드를 호출할 때까지 기다리세요. :) 이제 클라이언트 프로그램을 작성해 봅시다! 곱하기 위해 숫자를 우리 서버로 보냅니다. ServerMainClientMainmain()
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class ClientMain {

   public static final String UNIQUE_BINDING_NAME = "server.calculator";

   public static void main(String[] args) throws RemoteException, NotBoundException {

       final Registry registry = LocateRegistry.getRegistry(2732);

       Calculator calculator = (Calculator) registry.lookup(UNIQUE_BINDING_NAME);

       int multiplyResult = calculator.multiply(20, 30);

       System.out.println(multiplyResult);
   }
}
그녀는 복잡해 보이지 않습니다. 여기서 무슨 일이 일어나고 있는 걸까요? 첫째, 클라이언트는 원격으로 호출할 메서드가 포함된 개체의 고유 이름을 알고 있어야 합니다. 따라서 클라이언트 프로그램에서도 변수를 생성했으며 public static final String UNIQUE_BINDING_NAME = "server.calculator"; 다음으로 메소드에서 main()원격 개체의 레지스터에 액세스합니다. 이렇게 하려면 메소드를 호출 LocateRegistry.getRegistry()하고 ServerMain 프로그램에서 레지스터가 생성된 포트 번호인 포트 2732를 전달해야 합니다(이 번호는 예로 선택되었으므로 다른 번호를 사용해 볼 수 있습니다).
final Registry registry = LocateRegistry.getRegistry(2732);
이제 우리가 해야 할 일은 레지스터에서 원하는 객체를 얻는 것뿐입니다! 그의 고유한 이름을 알고 있기 때문에 쉽습니다!
Calculator calculator = (Calculator) registry.lookup(UNIQUE_BINDING_NAME);
타입 캐스팅에 주의하세요. 결과 객체를 구체적인 클래스가 아닌 인터페이스Calculator RemoteCalculationServer 로 캐스팅했습니다 . 강의 시작 부분에서 말했듯이 RMI는 Proxy 사용을 기반으로 하기 때문에 클래스가 아닌 인터페이스의 메소드에 대해서만 원격 호출이 가능합니다. 마지막에는 multiply()객체에 대한 메서드를 원격으로 호출하고 결과를 콘솔에 인쇄합니다.
int multiplyResult = calculator.multiply(20, 30);
System.out.println(multiplyResult);
우리는 오래 전에 main()클래스에서 메소드를 시작했습니다. 이제 클라이언트 프로그램에서 메소드를 시작할 시간입니다 ! 콘솔 출력: 600 그게 다입니다! 우리 프로그램 (두 개라도!) 은 그 기능을 성공적으로 수행했습니다 :) 시간과 욕구가 있다면 조금 다양화할 수 있습니다. 예를 들어 계산기가 숫자가 아닌 네 가지 표준 연산을 모두 지원하는지 확인하고 객체가 매개변수로 전달되는지 확인하세요 . 추가 자료로 기사와 예제를 볼 수 있습니다. 여기: ServerMainmain()ClientMainCalculationInstance(int x, int y) 다음 수업에서 만나요! :)
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION