수색…


비고

RMI에는 클라이언트, 서버 및 공유 원격 인터페이스의 세 가지 구성 요소가 필요합니다. 공유 원격 인터페이스는 서버가 구현해야하는 메소드를 지정하여 클라이언트 - 서버 계약을 정의합니다. 인터페이스는 메소드를 구현할 수 있도록 서버에서 볼 수 있어야합니다. 인터페이스는 클라이언트가 볼 수 있어야 서버가 제공하는 메소드 ( "서비스")를 알 수 있습니다.
원격 인터페이스를 구현하는 모든 객체는 서버의 역할을하도록 예정되어 있습니다. 따라서 서버가 클라이언트의 메소드를 호출 할 수있는 클라이언트 - 서버 관계는 실제로 서버 - 서버 관계입니다. 서버가 "클라이언트"를 콜백 할 수 있기 때문에이를 콜백 이라고합니다. 이를 염두에두고 기능하는 서버에 대해 지정 클라이언트 를 사용할 수 있습니다.

공유 원격 인터페이스는 Remote 확장하는 모든 인터페이스입니다. 서버로 작동하는 객체는 다음을 수행합니다.

  1. Remote 를 구현하는 UnicastRemoteObject 를 확장하는 것으로, 명시 적 또는 암묵적으로 공유 원격 인터페이스를 구현합니다.
  2. UnicastRemoteObject 확장하면 암시 적으로 내보내거나 UnicastRemoteObject#exportObject 에 전달하여 명시 적으로 UnicastRemoteObject#exportObject 있습니다.
  3. 직접 통해서, 레지스트리에 바인더 제본 Registry 또는 간접적 통해 Naming . 이것은, RMI를 통해서 직접적으로 스텁을 전달할 수 있기 때문에, 최초의 통신을 확립하는 경우에만 필요합니다.

프로젝트 설정에서 클라이언트와 서버 프로젝트는 완전히 무관하지만 각 프로젝트는 빌드 경로에 공유 프로젝트를 지정합니다. 공유 프로젝트에는 원격 인터페이스가 포함됩니다.

클라이언트 - 서버 : 다른 JVM에서 메소드를 호출

공유 원격 인터페이스 :

package remote;

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface RemoteServer extends Remote {

    int stringToInt(String string) throws RemoteException;
}

공유 원격 인터페이스를 구현하는 서버 :

package server;

import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;

import remote.RemoteServer;

public class Server implements RemoteServer {

    @Override
    public int stringToInt(String string) throws RemoteException {

        System.out.println("Server received: \"" + string + "\"");
        return Integer.parseInt(string);
    }

    public static void main(String[] args) {

        try {
            Registry reg = LocateRegistry.createRegistry(Registry.REGISTRY_PORT);
            Server server = new Server();
            UnicastRemoteObject.exportObject(server, Registry.REGISTRY_PORT);
            reg.rebind("ServerName", server);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
}

서버상의 메소드를 호출하는 클라이언트 (원격) :

package client;

import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

import remote.RemoteServer;

public class Client {

    static RemoteServer server;

    public static void main(String[] args) {

        try {
            Registry reg = LocateRegistry.getRegistry();
            server = (RemoteServer) reg.lookup("ServerName");
        } catch (RemoteException | NotBoundException e) {
            e.printStackTrace();
        }

        Client client = new Client();
        client.callServer();
    }

    void callServer() {
    
        try {
            int i = server.stringToInt("120");
            System.out.println("Client received: " + i);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
}

산출:

서버 수신 : "120"
고객 수신 : 120

콜백 : "클라이언트"

개요

이 예에서 클라이언트는 서버를 통해 정보를 서로 보냅니다. 한 클라이언트는 서버에 두 번째 클라이언트로 중계되는 번호를 보냅니다. 두 번째 클라이언트는 수를 반으로 나누고 서버를 통해 첫 번째 클라이언트로 다시 보냅니다. 첫 번째 클라이언트도 똑같이합니다. 서버는 클라이언트 중 하나가 리턴 한 번호가 10보다 작은 경우 통신을 중지합니다. 서버에서 클라이언트로의 리턴 값 (문자열 표현으로 변환 된 번호)은 프로세스를 역 추적합니다.

  1. 로그인 서버는 자신을 레지스트리에 바인드합니다.
  2. 클라이언트는 로그인 서버를 찾고 해당 정보로 login 메소드를 호출합니다. 그때:
    • 로그인 서버는 클라이언트 정보를 저장합니다. 여기에는 콜백 메소드가있는 클라이언트의 스텁이 포함됩니다.
    • 로그인 서버는 클라이언트에 저장하고 저장할 서버 스텁 ( "connection"또는 "session")을 작성하여 리턴합니다. 여기에는 logout 메소드 (이 예에서는 사용되지 않음)를 포함한 서버의 스텁이 포함됩니다.
  3. 클라이언트는 수신자 클라이언트의 이름과 int 하여 서버의 passInt 를 호출합니다.
  4. 서버는 해당 int 를 사용하여 수신자 클라이언트의 half 을 호출합니다. 이것은 서버에 의해 중단 될 때까지 앞뒤 (콜백 및 콜백) 통신을 시작합니다.

공유 원격 인터페이스

로그인 서버 :

package callbackRemote;

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface RemoteLogin extends Remote {

    RemoteConnection login(String name, RemoteClient client) throws RemoteException;
}

서버:

package callbackRemote;

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface RemoteConnection extends Remote {

    void logout() throws RemoteException;

    String passInt(String name, int i) throws RemoteException;
}

클라이언트 :

package callbackRemote;

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface RemoteClient extends Remote {

    void half(int i) throws RemoteException;
}

구현

로그인 서버 :

package callbackServer;

import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.util.HashMap;
import java.util.Map;

import callbackRemote.RemoteClient;
import callbackRemote.RemoteConnection;
import callbackRemote.RemoteLogin;

public class LoginServer implements RemoteLogin {

    static Map<String, RemoteClient> clients = new HashMap<>();

    @Override
    public RemoteConnection login(String name, RemoteClient client) {

        Connection connection = new Connection(name, client);
        clients.put(name, client);
        System.out.println(name + " logged in");
        return connection;
    }

    public static void main(String[] args) {

        try {
            Registry reg = LocateRegistry.createRegistry(Registry.REGISTRY_PORT);
            LoginServer server = new LoginServer();
            UnicastRemoteObject.exportObject(server, Registry.REGISTRY_PORT);
            reg.rebind("LoginServerName", server);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
}

서버:

package callbackServer;

import java.rmi.NoSuchObjectException;
import java.rmi.RemoteException;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.rmi.server.Unreferenced;

import callbackRemote.RemoteClient;
import callbackRemote.RemoteConnection;

public class Connection implements RemoteConnection, Unreferenced {

    RemoteClient client;
    String name;

    public Connection(String name, RemoteClient client) {

        this.client = client;
        this.name = name;
        try {
            UnicastRemoteObject.exportObject(this, Registry.REGISTRY_PORT);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void unreferenced() {

        try {
            UnicastRemoteObject.unexportObject(this, true);
        } catch (NoSuchObjectException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void logout() {

        try {
            UnicastRemoteObject.unexportObject(this, true);
        } catch (NoSuchObjectException e) {
            e.printStackTrace();
        }
    }

    @Override
    public String passInt(String recipient, int i) {

        System.out.println("Server received from " + name + ":" + i);
        if (i < 10)
            return String.valueOf(i);
        RemoteClient client = LoginServer.clients.get(recipient);
        try {
            client.half(i);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
        return String.valueOf(i);
    }
}

클라이언트 :

package callbackClient;

import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;

import callbackRemote.RemoteClient;
import callbackRemote.RemoteConnection;
import callbackRemote.RemoteLogin;

public class Client implements RemoteClient {

    RemoteConnection connection;
    String name, target;

    Client(String name, String target) {

        this.name = name;
        this.target = target;
    }

    public static void main(String[] args) {

        Client client = new Client(args[0], args[1]);
        try {
            Registry reg = LocateRegistry.getRegistry();
            RemoteLogin login = (RemoteLogin) reg.lookup("LoginServerName");
            UnicastRemoteObject.exportObject(client, Integer.parseInt(args[2]));
            client.connection = login.login(client.name, client);
        } catch (RemoteException | NotBoundException e) {
            e.printStackTrace();
        }

        if ("Client1".equals(client.name)) {
            try {
                client.connection.passInt(client.target, 120);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void half(int i) throws RemoteException {

        String result = connection.passInt(target, i / 2);
        System.out.println(name + " received: \"" + result + "\"");
    }
}

예제 실행 :

  1. 로그인 서버를 실행하십시오.
  2. Client2 Client1 1097 인수로 클라이언트를 실행하십시오.
  3. Client1 Client2 1098 인수를 사용하여 클라이언트를 실행하십시오.

3 개의 JVM이 있기 때문에 출력은 3 개의 콘솔에 나타납니다. 여기에 그들은 함께 묶여있다.

로그인 한 Client2
로그인 한 Client1
클라이언트 1에서 수신 한 서버 : 120
Client2로부터받은 서버 : 60
Client1에서받은 서버 : 30
Client2로부터받은 서버 : 15
Client1에서받은 서버 : 7
수신 된 Client1 : "7"
수신 된 Client2 : "15"
수신 된 Client1 : "30"
수신 된 Client2 : "60"

클라이언트 및 서버 구현을 사용한 간단한 RMI 예제

이것은 5 개의 자바 클래스와 2 개의 패키지 인 serverclient 를 가진 간단한 RMI 예제이다.

서버 패키지

PersonListInterface.java

public interface PersonListInterface extends Remote
{
    /**
     * This interface is used by both client and server
     * @return List of Persons
     * @throws RemoteException
     */
    ArrayList<String> getPersonList() throws RemoteException;
}

PersonListImplementation.java

public class PersonListImplementation 
extends UnicastRemoteObject 
implements PersonListInterface
{

    private static final long serialVersionUID = 1L;

    // standard constructor needs to be available
    public PersonListImplementation() throws RemoteException
    {}

    /**
     * Implementation of "PersonListInterface"
     * @throws RemoteException
     */
    @Override
    public ArrayList<String> getPersonList() throws RemoteException
    {
        ArrayList<String> personList = new ArrayList<String>();
        
        personList.add("Peter Pan");
        personList.add("Pippi Langstrumpf");
        // add your name here :)
        
        return personList;
    }
}

Server.java

public class Server {

    /**
     * Register servicer to the known public methods
     */
    private static void createServer() {
        try {
            // Register registry with standard port 1099
            LocateRegistry.createRegistry(Registry.REGISTRY_PORT);
            System.out.println("Server : Registry created.");

            // Register PersonList to registry 
            Naming.rebind("PersonList", new PersonListImplementation());
            System.out.println("Server : PersonList registered");

        } catch (final IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(final String[] args) {
        createServer();
    }
}

클라이언트 패키지

PersonListLocal.java

public class PersonListLocal {
    private static PersonListLocal instance;
    private PersonListInterface personList;

    /**
     * Create a singleton instance
     */
    private PersonListLocal() {
        try {
            // Lookup to the local running server with port 1099
            final Registry registry = LocateRegistry.getRegistry("localhost",
                    Registry.REGISTRY_PORT);

            // Lookup to the registered "PersonList"
            personList = (PersonListInterface) registry.lookup("PersonList");
        } catch (final RemoteException e) {
            e.printStackTrace();
        } catch (final NotBoundException e) {
            e.printStackTrace();
        }
    }

    public static PersonListLocal getInstance() {
        if (instance == null) {
            instance = new PersonListLocal();
        }

        return instance;
    }

    /**
     * Returns the servers PersonList
     */
    public ArrayList<String> getPersonList() {
        if (instance != null) {
            try {
                return personList.getPersonList();
            } catch (final RemoteException e) {
                e.printStackTrace();
            }
        }

        return new ArrayList<>();
    }
       }

PersonTest.java

public class PersonTest
{
    public static void main(String[] args)
    {
        // get (local) PersonList 
        ArrayList<String> personList = PersonListLocal.getInstance().getPersonList();
        
        // print all persons
        for(String person : personList)
        {
            System.out.println(person);
        }
    }
}

신청서 테스트

  • Server.java의 main 메소드를 시작하십시오. 산출:
Server : Registry created.
Server : PersonList registered
  • PersonTest.java의 main 메소드를 시작하십시오. 산출:
Peter Pan
Pippi Langstrumpf


Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow