Сетевой протокол на java

2. Архитектура Клиент-Сервер на сокетах Java

Наиболее распространённый способ создания распределённого приложения с клиент-серверной архитектурой – это использование сокетов.

1 Понятие сокета

  • Стили соединения гарантируют доставку всех пакетов в том порядке, в каком они были отправлены. Если во время передачи пакеты были потеряны или доставлены в неправильном порядке, получатель автоматически отправляет запрос на их повторную передачу. Стиль соединения напоминает телефонный звонок: адреса отправителя и получателя фиксируются в начале соединения, при установке подключения.
  • Стили дейтаграмм не гарантирует доставки и правильного порядка прибытия. Пакеты могут быть потеряны или переупорядочены в пути из-за сетевых ошибок. Каждый пакет должен быть помечен его адресатом, и нет гарантии, что он будет доставлен. Система гарантирует только «максимальные усилия», поэтому пакеты могут исчезнуть или прибыть в различном порядке. Сокет стиля дейтаграммы ведет себя сходно с почтой. Отправитель определяет адрес получателя для каждого индивидуального сообщения.

Пространство имен определяет, как записаны адреса сокета (socket addresses). Адрес сокета идентифицирует один конец подключения сокета. Например, адреса сокета в локальном пространстве имен являются обычными именами файлов. В пространстве имен Интернет-адрес сокета состоит из IP-адреса главного компьютера, присоединенного к сети, и номера порта, который идентифицирует сокет среди множества сокетов на том же главном компьютере (порты с 1 по 1024 зарезервированы операционной системой).

Протокол определяет, как передаются данные. Существуют следующие виды протоколов: TCP/IP, первичные сетевые протоколы, используемые Интернетом; сетевой протокол AppleTalk; локальный UNIX протокол взаимодействия. Не все комбинации стилей, пространств имен и протоколов поддерживаются.

Для организации обмена информацией по протоколу TCP обязательно требуется открыть соединение между конечными точками (характеризующимися IP-адресом и портом). При этом будут использоваться клиентские (их может быть несколько) и серверные (обычно он существует в единственном экземпляре) сокеты. Клиентские сокеты (на стороне клиента) пытаются открыть соединение с удаленной конечной точкой (на стороне сервера), а серверный сокет (на стороне сервера) ожидает или «слушает» входящие соединения. В общих чертах последовательность действий описывается следующим образом:

  • создание клиентского сокета;
  • установка параметров сокета (IP-адрес и порт, к которым необходимо подключиться);
  • установка соединения между сокетом и удаленной конечной точкой;
  • отправка/получение информации;
  • разрыв соединения и освобождение сокета.
  • создание серверного сокета;
  • установка параметров серверного сокета (IP-адрес и порт, на которые ожидаются подключения);
  • перевод серверного сокета в режим отслеживания входящих соединений;
  • при наличии входящего соединения: получить отдельный сокет для работы с этим конкретным соединением;
  • отправка/получение информации;
  • по окончании работы с клиентом: разрыв соединения и освобождение сокета, привязанного к этому клиенту;
  • по окончании работы сервера: освобождение серверного сокета.

2 Реализация сокетов на языке Java

Для создания соединения можно использовать API (Application Programming Interface), входящий в состав пакета java.net. Этот пакет предоставляет возможность для реализации сетевого взаимодействия с применением одного из двух транспортных протоколов: UDP и TCP.

2.1 Стек протоколов TCP/IP

Архитектура протоколов TCP/IP, известная как стек протоколов TCP/IP, возникла в результате исследований в области протоколов и разработок, выполнявшейся в экспериментальной сети с коммутацией пакетов под названием ARPANET, которая была основана Управлением перспективных исследовательских программ Министерства обороны США (DARPA).

Читайте также:  Интерфейс протокол компьютерных сетей это

В общем можно сказать, что в обмене информацией всегда принимают участие три агента: приложения, узлы (компьютеры) и сети. К приложениям относятся программы, предназначенные, например, для передачи файлов или электронной почты. Приложения, о которых идет речь, являются распределенными приложениями, включающими в себя обмен данными между двумя и более компьютерными системами. Компьютеры соединены между собой в сети, и предназначенные для обмена данные передаются по сети от одного компьютера к другому. Таким образом, передача данных от одного приложения другому (или от одного компонента другому в рамках одного распределенного приложения) включает в себя, во-первых, получение данных тем узлом, на котором находится приложение-адресат, и, во-вторых, получение данных именно тем выполняющимся на узле-адресате приложением, которому они предназначены (одновременно на узле могут выполняться несколько приложений).

Ввиду этого в задаче обмена информацией выделяют пять основных относительно независимых уровней:

  • физический уровень;
  • уровень доступа к сети (сетевой);
  • межсетевой уровень;
  • транспортный уровень;
  • уровень приложений.

На физическом уровне находится физический интерфейс между устройством передачи данных и передающей средой. На этом уровне задаются характеристики передающей среды, природа сигналов, скорость передачи данных и т.д.

Уровень доступа к сети связан с обменом данными между конечной системой (рабочей станцией, сервером и т.д.) и сетью, к которой подсоединена эта система. Узел-отправитель должен передать в сеть адрес узла-адресата, чтобы сеть могла направить данные по месту требования.

Уровень доступа к сети рассматривается в связи с доступом к сети и маршрутизацией данных между двумя подключенными к сети оконечными системами. В тех случаях, когда устройства подключены к разным сетям, нужны дополнительные процедуры, позволяющие данным переходить из одной сети в другую. Такие функции относятся к межсетевому уровню. На этом уровне функции межсетевой маршрутизации предоставляются с помощью Интернет-протокола (Internet ProtocolIP). Интернет-протокол может быть реализован не только в конечных системах, но и в маршрутизаторах.

Независимо от природы приложений обмен данными должен быть надежным, т.е. хотелось бы иметь уверенность в том, что все данные попали к приложению-адресату и что эти данные получены в том порядке, в котором они были отправлены. Механизмы обеспечения надежности, по сути, независимы от природы приложений, таким образом, имеет смысл выделить такие механизмы в один общий уровень, совместно используемый всеми приложениями. Этот уровень называется транспортным. Чаще всего для него применяется протокол управления передачей (Transmission Control ProtocolTCP).

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

Итак, чтобы обмен информацией был возможен, каждый элемент системы должен иметь уникальный адрес. Фактически, нужно указать два уровня адресации. Каждый узел сети должен обладать своим уникальным глобальным сетевым адресом, это позволит доставить данные соответствующему узлу. Каждый процесс (компонент) на узле должен иметь адрес, который был бы уникальным в пределах этого узла, что даст возможность транспортному протоколу (TCP) доставить данные нужному процессу. Этот адрес в терминологии протоколов семейства TCP/IP называют портом.

Читайте также:  Глобальная компьютерная сеть это в информатике определение

Для большинства приложений, выполняющихся в рамках архитектуры протокола TCP/IP, протоколом транспортного уровня выступает TCP. Этот протокол обеспечивает надежное соединение для передачи данных от одного приложения к другому. Кроме него существует еще один широко используемый протокол транспортного уровня, входящий в набор протоколов TCP/IP: пользовательский протокол дейтаграмм (User Datagram ProtocolUDP). Протокол UDP предоставляет сервис без установления соединения, предназначенный для процедур на уровне приложения; он не гарантирует доставку, сохранение последовательности при приеме переданных пакетов или защиту от их дублирования. Он позволяет процессу отправлять сообщения другим процессам, с помощью минимального протокольного механизма. Протокол UDP выполняет крайне ограниченный набор функций, так как работает без установления соединения, он только добавляет к протоколу IP некоторые возможности адресации портов.

2.2 Состав пакета java.net

2.2.1 Средства передачи по протоколу UDP

Для работы с UDP в пакете java.net определены следующие классы.

1. DatagramSocket — предназначен для посылки/приема UDP дейтаграмм.

  • DatagramSocket() — создаваемый сокет присоединяется к любому свободному порту на локальной машине;
  • DatagramSocket (int port) — создаваемый сокет присоединяется к порту port на локальной машине;
  • DatagramSocket(int port, InetAddress addr) — создаваемый сокет присоединяется к порту port ; аргумент addr – IP-адрес сервера.
  • send(DatagramPacket pack) — отправляет дейтаграмму, упакованную в пакет pack ;
  • receive(DatagramPacket pack) — дожидается получения дейтаграммы и заносит ее в пакет pack ;
  • setSoTimeout() — устанавливает тайм-аут для операций сокета;
  • close() — закрывает сокет.

2. DatagramPacket — предназначен для представления единичной дейтаграммы.

  • DatagramPacket(byte[] buf, int length) — служит для получения пакета длиной length , buf — буфер для получения дейтаграммы;
  • DatagramPacket(byte[] buf, int length, InetAddress addr, int port) — Создает пакет дейтаграммы длиной length , чтобы отправить его к указанному номеру порта ( port ) на указанном узле ( address ), buf — буфер, содержащий данные для передачи.

Кроме того пакет содержит вспомогательные методы:

  • connect(InetAddress addr, int port) — установить соединение;
  • disconnect() — разъединить;
  • InetAddress.getByName(host) — получить IP-адрес хоста;
2.2.2 Примеры UDP-соединения

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

Приведённая в примере программа создает сокет, соединяется с сервером (порт 2100), пересылает ему сообщение и ждет ответа:

import java.net.*; import java.io.*; public class UDPClient < public static void main(String args[])< try < // создаём сокет DatagramSocket aSocket = new DatagramSocket(); // задаём строку для передачи String str = "Hello"; // и преобразуем её в поток байт byte [] message = str.getBytes(); // получаем IP-адрес компьютера в формате Java InetAddress aHost = InetAddress.getByName("localhost"); // задаём порт int sPort = 2100; // создаём дейтаграмму, длина которой определяется длиной // сообщения DatagramPacket request = new DatagramPacket(message, message.length, aHost, sPort); // передаём серверу aSocket.send(request); // определяем буфер под ответ сервера byte [] buffer = new byte[1000]; // создаём дейтаграмму под ответ сервера DatagramPacket reply = new DatagramPacket(buffer, buffer.length); // принимаем ответ aSocket.receive(reply); // выводим ответ на консоль System.out.println("Reply: " + new String(reply.getData())); // закрываем сокет aSocket.close(); >catch (SocketException e) < // если не получилось создать сокет System.out.println("Socket: " + e.getMessage()); >catch (IOException e) < // ошибка при приеме System.out.println("IO: " + e.getMessage()); >> >

В первых строках кода происходит импорт необходимых библиотек (пакетов) классов — в нашем случае это java.net и java.io . Первый пакет содержит необходимые нам классы для работы с UDP, второй определяет необходимые классы ввода/вывода.

Читайте также:  Объединение компьютеров для обмена информацией и совместного использования ресурсов это

Класс называется UDPClient , он содержит единственный статический метод main() , являющийся точкой входа в программу. В нём создаётся сокет и пакет с текстовым сообщением, который затем будет передан серверу. После передачи происходит ожидание ответа от сервера, полученный ответ выводится на экран.

Адрес получателя определяется в пакете, а не в сокете, через который он передаётся. Поэтому один и тот же сокет может быть использован для передачи пакетов разным узлам, и этот же сокет может применяться для приема пакета от сервера. После использования сокет должен быть закрыт ( aSocket.close() ).

Пример UDP сервера:

Метод main() класса UDPServer создает сокет, принимает запрос клиента и возвращает клиенту полученное от него текстовое сообщение:

import java.net.*; import java.io.*; public class UDPServer < public static void main(String args[]) < DatagramSocket aSocket = null; try< // создаём сокет: порт 2100 aSocket = new DatagramSocket(2100); // резервируем буфер под клиентское сообщение byte [] buffer = new byte[1000]; while(true)< // бесконечный цикл // резервируем дейтаграмму под пакет клиента DatagramPacket request = new DatagramPacket(buffer, buffer.length); // принимаем пакет клиента aSocket.receive(request); // создаём ответную дейтаграмму DatagramPacket reply = new DatagramPacket(request.getData(), request.getLength(), request.getAddress(), request.getPort()); // отправляем ответ клиенту aSocket.send(reply); >> catch (SocketException e) < // обрабатываем ошибку создания сокета System.out.println("Socket: " + e.getMessage()); >catch (IOException e) < // обрабатываем ошибку передачи пакета System.out.println("IO: " + e.getMessage()); >finally < // закрываем сокет if(aSocket != null) aSocket.close(); >> >

После запуска сервер переходит в режим ожидания сообщений от клиента. Поскольку нами не предусмотрено никакого механизма останова сервера, выгрузить его может либо произошедшая ошибка, либо насильственное прерывание процесса.

После запуска клиент отправляет строку на сервер, печатает ее в консоли и завершает работу. Сервер же продолжает ожидать очередное подключение следующего клиента.

Сначала производится запуск сервера, а затем клиента.

2.2.3 Средства передачи по протоколу TCP

Конструктор: Socket(InetAddress host, int serverPort) – создаёт клиентский сокет, аргументы IP-адрес сервера и порт;

2. ServerSocket
Конструктор: ServerSocket(int serverPort) – служит для создания «слушающего» сокета на сервере.

Метод: accept() – ожидание сервером нового соединения.

Пример (на стороне сервера):

ServerSocket servsock = new ServerSocket(7896); Socket sock = servsock.accept();

Первая строка примера создаёт «слушающий» сокет сервера (ожидающий клиента). Во второй строке метод accept() серверного сокета ( servsock ) возвращает соответствующий сокет ( sock ) для общения с клиентом.

После сеанса связи сокеты следует закрыть, используя метод close() .

Источник

Оцените статью
Adblock
detector