Распределенная коммуникационная среда — rmi

задняя часть сервер HTTP Безопасность удаленная работа

Очки знаний:

1) Что такое рми
2) Простая реализация rmi
3) принцип РМИ
4) Рукописная структура RMI

Давайте сначала поговорим о RPC?

Протокол удаленного вызова процедур
Не зная специфики, вызов метода класса в удаленной системе аналогичен вызову локального метода.
Протокол RPC на самом деле является спецификацией.
В том числе Dubbo, Thrift, rmi, webservice, hessain

Сетевые протоколы и сетевой ввод-вывод прозрачны для вызывающей стороны и сервера.

Элементы, которые должна содержать структура RPC:

Обзор RMI

rmi (вызов удаленного метода) вызов удаленного метода
Можно рассматривать как Java-версию RPC.

RMI использует JRMP (JAVA Remote Messageing Protocol).Можно сказать, что JRMP — это коммуникационный протокол, специально настроенный для java, поэтому это чисто распределенное решение java.

Как реализовать программу RMI

1) Создайте удаленный интерфейс и наследуйте интерфейс java.rmi.Remote.

package com.llf.rmidemo;

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

public interface SayHello extends Remote{
	  public String sayHello(String name)throws RemoteException;
}

2) Реализовать наш удаленный интерфейс и унаследовать UnicastRemoteObject

package com.llf.rmidemo;

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

public class SayHelloImpl extends UnicastRemoteObject implements SayHello{

	protected SayHelloImpl() throws RemoteException {
	}

	@Override
	public String sayHello(String name) throws RemoteException {
		return "Hello LLF -->"+name;
	}

}

3) Создайте серверную программу и вызовите метод createRegistry для регистрации удаленного объекта.

package com.llf.rmidemo;

import java.net.MalformedURLException;
import java.rmi.AlreadyBoundException;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;

public class HelloServer {
	public static void main(String[] args) {
		try {
			SayHello hello=new SayHelloImpl();
			LocateRegistry.createRegistry(8888);
			try {
				Naming.bind("rmi://localhost:8888/sayhello", hello);
				System.out.println("Server start success!");
			} catch (MalformedURLException e) {
				e.printStackTrace();
			} catch (AlreadyBoundException e) {
				e.printStackTrace();
			}
		} catch (RemoteException e) {
			e.printStackTrace();
		}
	}

}

4) Создать клиентскую программу

package com.llf.rmidemo;

import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;

public class HelloClient {
	public static void main(String[] args) {
		try {
			SayHello hello=(SayHello) Naming.lookup("rmi://localhost:8888/sayhello");
			System.out.println(hello.sayHello("FXP"));
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (RemoteException e) {
			e.printStackTrace();
		} catch (NotBoundException e) {
			e.printStackTrace();
		}
	}

}

результат:

Внедрите RMI самостоятельно

1) Напишите серверную программу, выставьте прослушиватели и используйте сокеты. 2) Написать клиентскую программу, подключиться к указанному сервису через IP и порт и инкапсулировать (сериализовать) наши данные 3) Когда сервер получает запрос, он сначала десериализует его для обработки бизнес-логики, а затем сериализует и возвращает возвращаемый результат.

схема последовательности вызовов rmi framework

анализ исходного кода rmi

Мы можем почти понять это с помощью следующей диаграммы: а) Идентификаторы заглушки и скелета существуют как прокси. Клиент называется заглушкой, а сервер называется скелетом. Эти два объекта скрывают специфические детали удаленных вызовов методов. Эти два необходимы. b) Реестр: Реестр, который обеспечивает сопоставление имен сервисов с сервисами.

В сочетании с приведенным выше изображением и демонстрационным кодом выше, давайте взглянем на базовый исходный код rmi. Во-первых, давайте посмотрим на серверную часть, которая предоставляет услугу метод createRegistry

Сначала сервер создает объект RegistryImpl, а затем выполняет проверку безопасности, здесь не нужно обращать внимание, основное внимание уделяется методу установки.

Войдите в класс RegistryImpl

Затем введите метод exportObject UnicastServerRef. 1) Сначала создайте заглушку прокси-объекта для входящего RegistryImpl. 2) Установите объект скелета UnicastServerRef в текущий объект RegistryImpl. 3) скелет, заглушка, объект unicastserverRef, идентификатор и логическая конструкция целевого объекта

Далее находится метод экспорта exportObject.

Основной метод заключается в вызове метода listen для создания serversocket и запуска потока для ожидания клиентских запросов. Пока что наш сервер запустил службу, ожидающую подключения клиента.

клиент

Это на самом деле для создания прокси-объекта-заглушки

Используйте код для имитации основного процесса RMI следующим образом: Создайте новый объект пользователя

package com.llf.rmi;

public class User {
	
	private int age;

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

}

Напишите класс Skeleton для вызова клиентом [этот блок определяется rmi для защиты базовой сериализации и потокового соединения, здесь симуляция записывает базовую сериализацию и поток]

package com.llf.rmi;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;

//server程序
public class User_Skeleton extends Thread {

	private UserServer userServer;

	public User_Skeleton(UserServer userServer) {
		this.userServer = userServer;

	}

	public void run() {
		ServerSocket serverSocket = null;
		ObjectInputStream read = null;
		ObjectOutputStream oos = null;
		Socket socket=null;
		try {
			serverSocket = new ServerSocket(8888);
		    socket = serverSocket.accept();
			while (socket != null) {
				read = new ObjectInputStream(socket.getInputStream());
				String method = (String) read.readObject();
				if (method.equals("age")) {
					int age = userServer.getAge();
					oos = new ObjectOutputStream(socket.getOutputStream());
					oos.writeInt(age);
					oos.flush();
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (serverSocket != null) {
				try {
					oos.close();
					read.close();
					socket.close();
					serverSocket.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

написать заглушку

package com.llf.rmi;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

public class User_Stub extends User {
	private Socket socket;
	
	public User_Stub() {
		try {
			socket=new Socket("localhost", 8888);
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	public int getAge(){
		ObjectOutputStream oos=null;
		ObjectInputStream ois=null;
		try {
			oos=new ObjectOutputStream(socket.getOutputStream());
			oos.writeObject("age");
			oos.flush();
			
			ois=new ObjectInputStream(socket.getInputStream());
			return ois.readInt();
		} catch (IOException e) {
			e.printStackTrace();
		}finally {
			try {
				ois.close();
				oos.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}
		return 0;
	}

}

написать код сервера

package com.llf.rmi;

public class UserServer extends User{
	public static void main(String[] args) {
		UserServer server=new UserServer();
		server.setAge(18);
		//模拟rmi生成的skeleton代理对象
		User_Skeleton user_Skeleton=new User_Skeleton(server);
		user_Skeleton.start();
		
	}
}

написать клиентский код

package com.llf.rmi;

public class UserClient {
	public static void main(String[] args) {
		User user=new User_Stub();
		int age=user.getAge();
		System.out.println(age);
	}
}