원격 호출 RMI

하나.고객 및 서버 역할
기존 클라이언트/서버 모드에서 클라이언트가 서버를 요청합니다.서버는 전송 요청을 분석하고 응답을 얻어 클라이언트에게 전송합니다.그러나 이렇게 하려면 중간 전송 형식의 해석을 고려해야 한다.만약에 클라이언트가 요청의 전송과 해석에 관심을 가지지 않고 로컬 방법의 형식만 호출하여 결과를 얻지만 때때로 서비스를 제공하는 대상이 같은 가상 기기 안에 있지 않고 심지어java 가상 기기가 아니라면 어떻게 해야 합니까? 해결 방법은 클라이언트가 하나의 서비스 기기의 에이전트를 제공하고 고객이 직접 이 에이전트를 호출하며 이 에이전트는 고객과 서버의 교류를 책임집니다.마찬가지로 서버에도 에이전트를 설치하여 서버와 클라이언트의 통신을 책임진다.일반적인 방식으로 서버 방법을 호출합니다.다음 문제는 대리끼리 어떻게 통신하는 거예요?
RMI----------Java 원격 방법 호출 기술, 자바의 분포식 대상 간의 호출 지원
CORBA-------------- 일반적인 대상 요청 구조, 프로그래밍 언어로 작성된 모든 대상 간의 방법 호출을 지원하고, CORBA는 인터넷 인터넷-ORB 프로토콜(IIOP)을 사용하여 대상 간의 통신을 지원한다.
SOAP------------- 간단한 대상 접근 프로토콜, 그것도 독립적인 프로그래밍 언어입니다.XML 기반 전송 형식입니다.
또한 MicroSoft는 다른 기본 프로토콜인 COM을 사용하여 객체 간 통신을 지원합니다.
CORBA와 SOAP는 모두 언어에 독립적이며 클라이언트와 서버는 C, C++, 자바로 작성합니다. 대상이 처리할 수 있는 방법의 서명과 데이터 형식을 설명하기 위해 인터페이스 설명을 제공하기만 하면 됩니다.이 인터페이스 설명은 특수한 설명 언어로 CORBA의 경우 인터페이스 정의 언어(IDL)이고 SOAP의 경우 WSDL(Web Service 설명 언어)입니다.
CORBA는 더 효율적이고 SOAP는 웹 아키텍처에 더 적합한 시스템입니다.통신의 대상이 모두 Java로 이루어진다면 RMI를 사용하는 것이 가장 좋다.
 
2.원격 방법 호출
클라이언트 대상 --------------- 일반적으로 원격 호출을 시작하는 대상
서버 객체 --------------- 해당하는 원격 객체
2.1 메모리 루트와 매개 변수 그룹
캐시 루트--------- 클라이언트 코드가 원격 방법을 호출할 때 실제적으로 호출되는 로컬 방법이다. 우리는 이 프록시 대상을 캐시 루트라고 부른다. 캐시 루트는 서버에 있는 것이 아니라 서버에 있다. 캐시 루트는 원격 방법을 호출하는 데 필요한 매개 변수를 한 바이트로 묶는다. 이 패키지 과정은 하드웨어와 무관한 인코딩 방식으로 인코딩한다.
매개 변수 그룹 ----- 매개 변수를 인코딩하는 과정을 매개 변수 그룹이라고 하는데, 그 목적은 매개 변수를 가상 컴퓨터에서 전송하기에 적합한 형식으로 변환하는 것이다.
한 마디로 하면 클라이언트의 스텁은 다음과 같은 섹션으로 구성된 정보 블록을 구성합니다.
  • 사용된 원격 대상의 표시부호
  • 호출된 방법에 대한 설명
  • 그룹 후의 매개 변수

  • 그리고 이 정보 블록을 서버에 보내고 서버는 대상을 받아들여 모든 원격 방법으로 다음 동작을 수행합니다
  • 반편성 파라미터
  • 호출할 대상을 지정합니다
  • 필요한 방법을 호출합니다
  • 반환값이나 호출로 인한 이상을 포착하여 그룹화한다
  • 반환 값을 그룹화하고 클라이언트 메모리로 포장합니다

  • 클라이언트 메모리는 반환된 값 그룹을 반컴파일합니다. 원격 방법으로 이상을 던지면 클라이언트 메모리는 클라이언트 처리 공간에서 다시 이상을 던집니다.
    2.2 동적 클래스 로드
    원격 대상이 원격 방법의 매개 변수나 반환 값으로 다른 프로그램에 전달될 때, 이 프로그램은 분명히 이 대상의 클래스 파일을 필요로 한다.
     
    셋.원격 호출 설정
    우선, 당신은 클라이언트와 서버에서 프로그램을 동시에 실행해야 합니다. 그 다음에 필요한 대상 정보는 클라이언트 인터페이스와 서버로 구분됩니다.클라이언트가 서버의 대상을 정확하게 포지셔닝할 수 있도록 전문적인 조회 메커니즘도 있다
    3.1 인터페이스와 실현
    클라이언트는 서버 대상을 조종해야 할 수도 있지만, 실제로는 진정한 서버 대상의 인용이 필요하지 않다. 왜냐하면 이 대상이 무엇을 할 수 있는지만 알면 되기 때문이다. 우리는 인터페이스를 사용하여 그것이 무엇을 할 수 있는지 설명할 수 있기 때문이다.이러한 인터페이스는 클라이언트와 서버가 공유하는 것으로 클라이언트와 서버에 동시에 존재해야 한다.원격 객체의 인터페이스는 Remote와 상속되어야 합니다.그리고 RemoteException 이상을 던져야 합니다.
    package rmi;
    
    import java.rmi.Remote;
    import java.rmi.RemoteException;
    
    public interface Product extends Remote {
    	String getDescription() throws RemoteException;
    }
    

     
    그리고 서버에서 이 인터페이스를 실현해야 합니다
    서버 클래스는 일반적으로 RemoteServer를 상속합니다.
    package rmi;
    
    import java.rmi.RemoteException;
    import java.rmi.server.UnicastRemoteObject;
    
    public class ProductImpl extends UnicastRemoteObject implements Product {
    
    	private String desc;
    	
    	public ProductImpl(String desc) throws RemoteException {
    		super();
    		this.desc = desc;
    	}
    
    	@Override
    	public String getDescription() throws RemoteException {
    		// TODO Auto-generated method stub
    		return "I am a "+desc+"buy me!";
    	}
    
    }
    

     
    3.2 캐시 클래스 생성
    JDK5.0부터는 자동으로 루트 클래스가 생성되지만 그 전에 루트 클래스를 수동으로 생성해야 합니다.
    rmic -v1.2 ProductImpl
    두 개의 파일을 생성합니다. ProductImpl_Stub.class 및 ProductImpl_Skel.class
    3.3 서버 객체 찾기
    서버의 원격 대상에 접근하려면 클라이언트 캐시를 얻어야 합니다. 가장 직접적인 방법은 원격 방법을 호출하여 반환값을 얻어 캐시를 되돌려야 합니다. 그러나 이렇게 첫 번째 원격 대상을 어떻게 얻을 수 있습니까?RMI 라이브러리는 첫 번째 서버 객체를 지정하기 위해 자체 등록 서비스를 제공합니다.자진 등록 서비스에 대상의 인용과 이름을 제공함으로써 서버 대상을 등록할 수 있고 클라이언트는 대상의 캐시를 얻을 수 있다.이 대상의 이름은 가장 유일하다.
     
    package rmi;
    
    import java.rmi.RemoteException;
    
    import javax.naming.Context;
    import javax.naming.InitialContext;
    import javax.naming.NamingException;
    
    public class ProductServer {
    
    	/**
    	 * @param args
    	 */
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		try {
    			System.out.println("Constructing server implementations...");
    
    			ProductImpl p1=new ProductImpl("boy");
    			
    			ProductImpl p2=new ProductImpl("girl");
    			
    			System.out.println("Binding server implementations to registry...");
    			Context namingContext = new InitialContext();
    			
    			namingContext.bind("rmi:b",p1);
    			namingContext.bind("rmi:g",p2);
    			
    			System.out.println("Waiting for invocation from clients....");
    		} catch (RemoteException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		} catch (NamingException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		
    	}
    
    }
    

     
    1. 서버 시작(윈도우즈)
    start rmiregistry
    start java ProductServer
    2. 원격 객체 열거
    NamingEnumeration e = namingContext.list("rmi:");
    package rmi2.ShowBindings;
    
    
    /**
       @version 1.10 2004-08-14
       @author Cay Horstmann
    */
    
    import java.rmi.*;
    import java.rmi.server.*;
    import javax.naming.*;
    
    /**
       This programs shows all RMI bindings.
    */
    public class ShowBindings
    {  
       public static void main(String[] args)
       {  
          try
          {  
             Context namingContext = new InitialContext();
             NamingEnumeration<NameClassPair> e = namingContext.list("rmi:");
             while (e.hasMore())
                System.out.println(e.next().getName());
          }
          catch (Exception e)
          {  
             e.printStackTrace();
          }
       }
    }
    

     
    3.4 클라이언트 코드 작성
    RMI를 사용하는 클라이언트는 캐시 루트를 동적으로 로드하기 위해 보안 관리자를 설치해야 합니다.
    System.setSecurityManager(new RMIsetSecurityManager)
    package rmi2.Product;
    
    /**
       @version 1.20 2004-08-15
       @author Cay Horstmann
    */
    
    import java.rmi.*;
    import java.rmi.server.*;
    import javax.naming.*;
    
    /**
       This program demonstrates how to call a remote method
       on two objects that are located through the naming service.
    */
    public class ProductClient
    {  
       public static void main(String[] args)
       {  
          System.setProperty("java.security.policy", "client.policy");
          System.setSecurityManager(new RMISecurityManager());
          String url = "rmi://localhost/";
             // change to "rmi://yourserver.com/" when server runs on remote machine yourserver.com
          try
          {  
             Context namingContext = new InitialContext();
             Product c1 = (Product) namingContext.lookup(url + "toaster");
             Product c2 = (Product) namingContext.lookup(url + "microwave");         
    
             System.out.println(c1.getDescription());
             System.out.println(c2.getDescription());
          }
          catch (Exception e)
          {  
             e.printStackTrace();
          }
       }
    }
    

     
    클라이언트가 RMI 레지스트리와 서버 객체에 연결할 수 있도록 하려면 정책 파일을 제공해야 합니다.서버 객체는 1024 이상의 포트를 사용하고 RMI 기본 포트는 1099입니다.
    client.policy
    grant 
    {  
       permission java.net.SocketPermission 
          "*:1024-65535", "connect,accept";
       permission java.net.SocketPermission 
          "localhost:80", "connect";
    };
    

    아무튼
  • 컴파일 인터페이스, 실현 클래스, 서버 클래스, 클라이언트 클래스 등 파일
  • RMI 레지스트리 start rmiregistry 를 시작합니다

  • RMI의 배치는 상당히 번거롭다. 보통 초보자는 실수를 하기 쉬우므로 나도 깊이 연구하고 공부하지 않았다. 여기서 나도 말하지 않겠다.관심 있는 사람은 Google에서 검색할 수 있습니다.
     
    사.원격 방법의 매개 변수 전달
    4.1 비원격 객체 전달
    원격 대상이 아닌 대상이 한 자바 가상 기기에서 다른 자바 가상 기기를 전송해야 할 때 첫 번째 자바 가상 기회는 대상 COPY를 만들고 네트워크를 통해 다른 가상 기기로 전송한다. 대상을 로컬 방법으로 전달하는 것은 인용일 뿐이다.
    그래서 원격 대상은 메모리를 통해 전달되고, 비원격 대상은 복제를 통해 전달된다.
    언제든지 원격 방법을 호출할 때 메모리 루트는 모든 매개 변수 값의 복사본을 포장하여 서버에 보냅니다. 그 중에서 대상 서열화 메커니즘으로 매개 변수를 그룹화합니다.

    좋은 웹페이지 즐겨찾기