Основной целью лабораторной работы является изучение принципов построения распределённых систем и закрепление полученных теоретических знаний на практике путём разработки проекта с использованием протокола удаленного вызова процедур JSON-RPC.
\section{JSONRPC2 Java}
Для разработки программ по заданию 1 использовалась IntelliJ IDEA 2021.3 Community Edition (далее IDEA). Для работы с JSONRPC2.0 в секции зависимостей сборщика проектов Gradle были указаны следующие пакеты:
Для программы реализующий сервер был использован код из примера первого задания. Код сервера представлен в листинге \hyperref[lst:server]{\ref{lst:server}}.
public static class DateTimeHandler implements RequestHandler {
public String[] handledRequests() {
return new String[]{"getDate", "getTime"};
}
public JSONRPC2Response process(JSONRPC2Request req, MessageContext ctx) {
if (req.getMethod().equals("getDate")) {
DateFormat df = DateFormat.getDateInstance();
String date = df.format(new Date());
return new JSONRPC2Response(date, req.getID());
} else if (req.getMethod().equals("getTime")) {
DateFormat df = DateFormat.getTimeInstance();
String time = df.format(new Date());
return new JSONRPC2Response(time, req.getID());
} else {
return new JSONRPC2Response(JSONRPC2Error.METHOD_NOT_FOUND, req.getID());
}
}
}
public static void main(String[] arg) {
JSONRPC2Parser parse = new JSONRPC2Parser();
Dispatcher dispatcher = new Dispatcher();
String line;
JSONRPC2Request req;
JSONRPC2Response res;
dispatcher.register(new DateTimeHandler());
try {
ServerSocket ss = new ServerSocket(3333);
System.out.println("Waiting for a client...");
while (true) {
Socket socket = ss.accept();
DataInputStream in = new DataInputStream(socket.getInputStream());
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
line = in.readUTF();
System.out.println("Request: " + line);
req = parse.parseJSONRPC2Request(line);
res = dispatcher.process(req, null);
line = res.toJSONObject().toJSONString();
System.out.println("Response: " + line);
out.writeUTF(line);
out.flush();
}
} catch (Exception x) {
x.printStackTrace();
}
}
}
\end{lstlisting}
\subsection{Клиент}
Для программы реализующей клиента был использован код из примера первого задания. Код клиента был переработан в виде тестового стенда для сервера и представлен в листинге \hyperref[lst:client]{\ref{lst:client}}
System.out.println("Date on Server - " + answerJSON.getResult());
}
}
\end{lstlisting}
\subsection{Результат работы}
После запуска приложения сервера оба теста возвращают положительный результат, представленный на рисунках \hyperref[pic:serverTests]{\ref{pic:serverTests}} и \hyperref[pic:serverTestsCl]{\ref{pic:serverTestsCl}}
Для разработки программ по заданию 2 использовалась JetBrains PyCharm 2021.3 Community Edition (далее PyCharm). Для работы с JSONRPC была скачана реализация протокола JSONRPC. Так же была установлена необходимая для работы библиотека SimpleJSON. Библиотека SimpleJSON была подключена к проекту при помощи пакетного менеджера \code{pip}. Библиотека JSONRPC была скачана в корень проектов сервера и клиента. На рисунке \hyperref[pic:contentPy]{\ref{pic:contentPy}} представлен снимок экрана с файлами проекта и загруженными библиотеками
Для программы, реализующей сервер был использован незначительно модифицированный код из примера второго задания. Код сервера представлен в листинге \hyperref[lst:pythonServer]{\ref{lst:pythonServer}}
\begin{lstlisting}[language=Python, caption=Сервер на языке Python, style=PyCodeStyle, label={lst:pythonServer}]
Для программы, реализующей клиент также был использован незначительно модифицированный код из примера второго задания. Код клиента представлен в листинге \hyperref[lst:pythonClient]{\ref{lst:pythonClient}}
\begin{lstlisting}[language=Python, caption=Клиент на языке Python, style=PyCodeStyle, label={lst:pythonClient}]
import jsonrpc
if __name__ == '__main__':
server = jsonrpc.ServerProxy(jsonrpc.JsonRpc20(), jsonrpc.TransportTcpIp(addr=("127.0.0.1", 31415)))
result = server.echo("hello world")
print(result)
result = server.multiply(a=3, b=5)
print(result)
result = server.multiply()
print(result)
\end{lstlisting}
\subsection{Результат работы}
Приложения сервера и клиента были запушены и протестированы. Результат работы сервера, журнал работы, представлен на рисунке \hyperref[pic:pysrvWork]{\ref{pic:pysrvWork}}, а результат работы клиента на рисунке \hyperref[pic:pycliWork]{\ref{pic:pycliWork}}.
Заданием для практической части является создание клиент-серверного приложения где клиент и сервер разработаны на разных языках. Клиент должен позволять формировать две матрицы заданного размера и посылать эти матрицы на сервер. Сервер в свою очередь должен суммировать полученные матрицы и отсылать результат клиенту. В качестве сервера была использована программы на Python реализованная во второй части задания. В качестве клиента была использована программа на Java реализованная в первой части задания. Код сервера был модифицирован для решения задачи сложения матриц. Код сервера представлен в листинге \hyperref[lst:pythonServerMatrix]{\ref{lst:pythonServerMatrix}}
Код клиента был модифицирован для возможности ввода размерности матриц, самих матриц и их вывода в консоль. Код клиента представлен в листинге \hyperref[lst:finalClient]{\ref{lst:finalClient}}
\begin{lstlisting}[language=Java, caption=Код со вводом матриц, style=JCodeStyle, label={lst:finalClient}]
package ru.iovchinnikov.rpcsample.server;
import com.thetransactioncompany.jsonrpc2.*;
import java.net.*;
import java.io.*;
import java.util.*;
public class Client {
static JSONRPC2Parser parse = new JSONRPC2Parser();
Приложения сервера и клиента были запушены и протестированы. Результат работы сервера представлен на рисунке \hyperref[pic:pysrvFin]{\ref{pic:pysrvFin}}, а результат работы клиента на рисунке \hyperref[pic:jcliFin]{\ref{pic:jcliFin}}.
В ходе выполнения работы была реализованная задача создания распределенной системы, где вся логика обработки данных предоставляется серверу, тогда как работа с данными происходит на клиенте.
Для реализации задачи был использован протокол удаленных вызовов процедур JSON-RPC. Протокол использует JSON для кодирования сообщений. Протокол был использован исходя из рекомендаций к заданию и имеет следующий особенности:
\begin{itemize}
\item небольшой размер;
\item простота использования;
\item документированность;
\item компактность и ёмкость одного выражения;
\item независимость от способа передачи данных;
\item поддержка именованных параметров;
\item поддержка нотификаций;
\item поддержка значений null(None);
\item встроенный контроль сессий;
\end{itemize}
Использование протокола позволяет создавать системы где сервер разрабатывается на одном языке программирование, а клиенты на других.