20 просмотров
Рейтинг статьи
1 звезда2 звезды3 звезды4 звезды5 звезд
Загрузка...

Максимально простой в поддержке способ интеграции java-клиента с java-сервером

Максимально простой в поддержке способ интеграции java-клиента с java-сервером

При решении повседневных задач с интерфейсом настольного приложения, реализованного на JavaFX, приходится в любом случае делать запрос на веб-сервер. После времен J2EE и страшной аббревиатуры RMI многое изменилось, а вызовы на сервер стали более легковесными. Как нельзя кстати для подобной проблемы подходит стандарт веб-сокетов и его обмен простыми текстовыми сообщениями любого содержания. Но проблема корпоративных приложений в том, что разнообразность и количество запросов превращает создание и отслеживание EndPoint-ов при наличии отдельно выделенных бизнес-сервисов в жуткую рутину и добавляет лишних строк кода.

А что если взять за основу строго типизированную стратегию с RMI, где между клиентом и сервером существовал стандартный java interface, описывающий методы, аргументы и возвращаемые типы, где добавлялось пару аннотаций, и волшебным образом клиент даже не замечал, что идет вызов по сети? Что если по сети передавать не просто текст, а сериализованные java-объекты? Что если добавить к этой стратегии легкость веб-сокетов и их преимущества возможности push-вызовов клиента со стороны сервера? Что если асинхронность ответов веб-сокета для клиента обуздать в привычный блокирующий вызов, а для отложенного вызова добавить возможность возвращения Future или даже CompletableFuture? Что если добавить возможность подписки клиента на определенные события от сервера? Что если на сервере иметь сессию и подключение к каждому клиенту? Может получиться неплохая прозрачная связка привычная любому java-программисту, так как за интерфейсом будет скрыта магия, а в тестировании интерфейсы легко подменить. Но вот только это все не для нагруженных приложений, обрабатывающих, например, котировки с фондовой биржи.

В корпоративных приложениях из моей практики скорость выполнения sql-запроса и передачи выбираемых данных из СУБД несоизмеримы с накладными расходами на сериализацию и рефлексивные вызовы. Более того страшная трассировка EJB-вызовов, дополняющая длительность выполнения до 4 — 10 мс даже на самый простенький запрос не является проблемой, так как длительность типичных запросов находится в коридоре от 50мс до 250мс.

Начнем с самого простого — воспользуемся паттерном Proxy-объект для реализации магии за методами интерфейса. Предположим, что у меня есть метод получения истории переписки пользователя с его оппонентами:

Proxy-объект создадим стандартными средствами java, и вызовем на нем нужный метод:

Если при этом настроить фабрики, а экземпляр proxy-объекта внедрять по интерфейсу через cdi-инъекцию, то получится магия в чистом виде. При этом открывать/закрывать сокет каждый раз совсем не обязательно. Напротив в моих приложениях сокет постоянно открыт и готов к приему и обработке сообщений. Теперь стоит посмотреть, что такого происходит в RMIoverWebSocketProxyHandler:

А вот собственно сам клиентский EndPoint:

Таким образом, на вызов любого метода proxy-объекта берем открытую сессию сокета, шлем переданные аргументы и реквизиты метода, который необходимо вызвать на сервере, и wait-имся до получения ответа с указанными ранее в запросе гуидом. При получении ответа проверяем на наличие исключения, и, если все хорошо, то кладем в Request результат ответа и нотифицируем поток, ожидающий ответа в WaitList-е. Реализацию такого WaitList-а приводить не буду, так как она тривиальна. Ожидающий поток в лучшем случае продолжит работать после строки WaitList.putRequest(request, getRequestRunnable(request));. После пробуждения поток проверит наличие задекларированных в секции throws исключений, и выполнит возврат результата через return.

Приведенные примеры кода являются выдержкой из библиотеки, которая пока не готова для выкладки на github. Необходимо проработать вопросы лицензирования. Реализацию серверной стороны имеет смысл смотреть уже в самом исходном коде после его опубликования. Но ничего особенного там нет — выполняется поиск ejb-объекта, который реализует указанный интерфейс, в jndi через InitialContext и делается рефлексивный вызов по переданным реквизитам. Там конечно еще много чего интересного, но ни в одну статью такой объем информации не влезет. В самой библиотеке приведенный сценарий блокирующего вызова был реализован в первую очередь, так как является самым простым. Позже была добавлена поддержка неблокирующих вызовов посредством Future и CompletableFuture<>. Библиотека успешно используется во всех продуктах с настольным java-клиентом. Буду рад, если кто-то поделится опытом открытия исходного кода, который линкуется с gnu gpl 2.0 (tyrus-standalone-client).

В итоге построить иерархию вызова метода стандартными средствами IDE до самой UI-формы, на которой обработчик кнопки дергает удаленные сервисы, не составляет труда. При этом получаем строгую типизацию и слабую связанность слоя интеграции клиента и сервера. Структура исходного кода приложения делится на клиент, сервер и ядро, которое подключается зависимостью и в клиент, и в сервер. Именно в нем и находятся все удаленные интерфейсы и передаваемые объекты. А рутинная задача разработчика, связанная с запросом в БД, требует нового метода в интерфейсе и его реализации на стороне сервера. На мой взгляд, куда уж проще.

Клиент-сервер на Java

Это первое приложение в односторонней связи. В случае односторонней связи клиент отправляет на сервер, но сервер не отправляет обратно клиенту. При двусторонней связи клиент отправляет на сервер, а сервер отправляет обратно клиенту.

Всего в приложении TCP / IP 4 варианта.

1-е Приложение клиент-сервер

Приложение состоит из двух программ. Клиентская программа, работающая на стороне клиента, и серверная программа, работающая на стороне сервера. Клиентская программа WishesClient.java отправляет серверу наилучшие пожелания, а серверная программа WishesServer.java получает сообщение и печатает на своем терминале (мониторе).

Клиентская программа — WishesClient.java

Конструктор класса Socket принимает два параметра — строку, IP-адрес сервера и целое число, номер порта на сервере, к которому клиент хотел бы подключиться. 127.0.0.1 — это адрес по умолчанию локальной системы в компьютерных сетях.

OutputStream ostream = sock.getOutputStream ();

Метод getOutputStream() класса Socket возвращает объект OutputStream, здесь объект является ostream. Это отправная точка всего общения (программы). Здесь сокет связан с потоками. Потоки способствуют передаче данных.

OutputStream является абстрактным классом; он не может быть использован напрямую. В приведенном выше коде он связан с конкретным классом DataOutputStream. Метод writeBytes() объекта DataOutputStream принимает строковое сообщение и передает его в Socket. Теперь клиентский сокет отправляется на другой сокет на сервере. Когда работа закончится, закройте потоки и сокет. Он освобождает дескрипторы (ссылки), связанные с системными ресурсами.

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

  • Socket(«127.0.0.1», 5000) выдает UnknownHostException
  • getOutputStream() генерирует IOException
  • writeBytes (message1) выдает IOException
  • Все методы close() выдают IOException
  • Серверная программа — WishesServer.java


ServerSocket sersock = новый ServerSocket (5000);

У сервера есть два задания: одно, как и ожидалось, должно связываться, а другое связывает соединение с номером порта 5000. Для связи он использует Socket, а для привязки — ServerSocket.

Связывание — это не что иное, как выделение номера порта клиенту так долго, как ему хотелось бы; Между тем, если какой-либо другой клиент запрашивает номер порта 5000, он не должен выделяться сервером. Когда клиент отключается, порт освобождается и может быть предоставлен другому клиенту сервером.

Socket sock = sersock.accept ();

accept() — это метод класса ServerSocket, используемый сервером для привязки соединения по номеру порта 5000, запрошенного клиентом.

InputStream istream = sock.getInputStream();

Метод getInputStream() объекта Socket возвращает объект InputStream, и это отправная точка серверной программы. Сервер использует входной поток при получении сообщения.

DataInputStream dstream = new DataInputStream (istream);

Поскольку InputStream является абстрактным классом, его нельзя использовать напрямую. Он связан с конкретным классом DataInputStream.

String message2 = dstream.readLine();

Метод readLine() объекта DataInputStream читает строку сообщения из сокета и возвращает ее. Это сообщение печатается на консоли.

Примечание. При компиляции этой программы вы получаете предупреждение из-за метода readLine() объекта DataInutStream; но программа выполняется. Чтобы избежать этого предупреждения, в следующей программе используется BufferedReader.

Выполнение клиентских и серверных программ

В одной системе, чтобы действовать как клиент и сервер, откройте два шDOS и обработайте одно как клиент, а другой — как сервер. Из одного приглашения DOS сначала запустите серверную программу, а из другого приглашения DOS запустите клиентскую программу. Вы получаете вывод при запросе сервера DOS.

Читать еще:  0x80070643 в процессе установки произошла неисправимая ошибка

Это приложение и следующее — только односторонняя связь, отправляющая или получающая. Но второй набор (после следующего) приложений является двусторонним, когда клиент и сервер могут отправлять и получать (оба). Для тестирования на выделенных серверах, можно обратиться сюда https://www.mixtelecom.ru/arenda-serverov.html

Для лучшего понимания вопрос-ответ из пакета java.lang.

Сколько существует типов внутренних классов?
Ответ: 4 типа.

Что такое файлы JAR?
Ответ: JAR-файл — это заархивированный файл, сжатый JVM.

Как преобразовать строку в форму типа данных?
Ответ: Преобразование строки в тип данных — байтовое, короткое, целое, длинное, плавающее, двойное, символьное и логическое.

Как преобразовать объект в строку?
Ответ: Объект в строку — toString()

Как сравнить два объекта?
Ответ: Сравнение объектов — hashCode() & equals()

Средняя оценка / 5. Количество голосов:

Спасибо, помогите другим – напишите комментарий, добавьте информации к статье.

Или поделись статьей

Видим, что вы не нашли ответ на свой вопрос.

Пример простого клиент-серверного приложения на Java

«Клиент-сервер» это очень распространенная и логичная архитектура приложений. Мне кажется, что в наши дни редко можно встретить standalone-клиентское приложение. Поэтому я принял решение рассмотреть пример построения клиент-серверного приложения на Java без привязки к конкретной задаче. Сначала вкратце пробежимся по классовой структуре приложения, потом посмотрим на отдельную реализацию каждого класса. В самом конце статьи я дам ссылку на скачивание архива с готовой структурой приложения. Итак, начнем.

Основные компоненты приложения

Основными компонентами, естественно, являются непосредственно клиент и сервер. Однако, кроме них необходим еще пакет вспомогательных классов, которые, в простейшем случае, будут отвечать за обмен сообщениями между клиентом и сервером. В минимальной комплектации нужны такие классы: MessageReader/MessageWriter(считывает/записывает сообщение в поток на сокете), MessageFactory(содержит идентификаторы всех возможных сообщений), набор сообщений-запросов(Request) и набор сообщений-ответов(Response). Все они будут размещены в пакете «core», который должны иметь у себя и клиент и сервер.

Рассмотрим классовую структуру всего проекта, а потом перейдем к реализации.

Классовая структура клиент-серверного приложения

Исходный код клиента на Java

Разобраться с клиентом гораздо проще, он по сути своей не делает ничего супер сложного, просто создает сокет и подключается к сервер-сокету с помощью связки host:port. Лаунчер создает объект класса Client и запускает его работу. Исходный код привожу без импортов, ибо любая IDE вам их подключит(те, кто пишет на Java точно знают, что без IDE очень сложно). Кроме того, в конце статьи вы сможете скачать архив с этим проектом.

ClientLauncher.java

Client.java

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

Исходный код сервера на Java

Задача сервера поднять свой серверный сокет на нужном адресе и ждать новых подключений. Для каждого подключения, которое принято называть клиентской сессией, создается отдельный поток обработки логики работы с клиентом.

Напомню, что в классе ClientSession описан основной алгоритм работы с клиентом, обмен сообщениями, данными и прочее. В классе Context содержится общая информация для всех клиентов сервера, например, пути для сохранения логов.

ServerLauncher.java

Server.java

Context.java

ClientSession.java

SessionsManager.java

Вспомогательные классы из пакета «core»

Помещу все вспомогательные классы под один кат, название классов в точности соответствует названиям из списка «классовая структура» выше, по нему вы можете определить пакет каждого класса.

Пара слов о сообщениях, классы Request и Response являются абстрактными и играют роль классификаторов сообщения. Благодаря этому очень удобно разграничивать «запросы» от «ответов». В этом примере я привел только одно сообщение — Handshake, которое отвечает за первое «рукопожатие» клиента и сервера. Все последующие сообщения должны быть прописаны в классе MessageFactory по примеру этих двух.

Скачать архив с шаблоном клиент-серверного приложения на Java

Заключение

Главная цель, которую я преследовал при написании этой статьи заключается в том, чтобы дать возможность мне или кому-либо еще за считанные минуты «собрать» готовое клиент-серверное приложение. Кажется, я с этим справился, если будут дополнения или замечания, пишите в комментариях или на почту. А на сегодня у меня все, спасибо за внимание!

KVERNER

Matlab Simulink Python Java HELP Работы программиста профессионала

Что такое сервлет Java? Обработка запросов для веб-приложений Java

Обработка запросов — это основа основ разработки веб-приложений Java. Чтобы отвечать на запросы из сети, веб-приложение Java сначала должно определить, какой код будет отвечать на URL-адрес запроса, а затем перенаправлять ответ. У каждого стека технологий есть способ выполнения обработки запроса-ответа. В Java для этой цели используется сервлеты.

ПО как слои

Каждый уровень в программной системе содержит определенные возможности, которые требуются для слоев над ним. В качестве примера, аппаратный уровень находится ниже уровня прошивки, поддерживая его функциональность. Аналогично, для запуска операционной системы необходим уровень прошивки (BIOS на ПК или EFI на Mac). На рисунке 1 показаны эти три компонента на многоуровневой диаграмме.

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

Серверная Java-версия

Серверное Java-приложение является одним из широкого класса приложений, которые служат в качестве конечных точек сети, получая HTTP-запросы с заданного URL-адреса и отправляя обратно данные в формате обмена, например HMTL или JSON. Серверное приложение Java состоит из стандартизированных Java-серверов и технологий для взаимодействия с этими серверами. Java Servlet API — это стандарт, используемый для взаимодействия с сервером Java.

Серверы Java и JVM

В Java-системах операционная система (ОС) содержит JVM, которая обеспечивает согласованную среду для работы приложений Java. Сервер Java находится поверх JVM. Подобно тому, как JVM является посредником между ОС и вашим Java-приложением, сервер Java обеспечивает последовательный, упрощенный доступ к возможностям сети и обработки операционной системы. Java-приложение запускается внутри сервера, используя API-интерфейс (Java Servlet) для доступа к возможностям сервера.

На рисунке 2 показан стек программного обеспечения для серверной Java.

Спецификация Java Servlet

Спецификация Java Servlet предоставляет базовое определение для сервера Java и связанных с ним компонентов. Он определяет, как сервер будет отправлять запросы и ответы во время сетевых взаимодействий через HTTP. Все серверы Java должны быть совместимы с спецификацией Java Servlet. Большинство Java-серверов сегодня совместимы с Servlet 4.0.

Для практического понимания того, как работает спецификация сервлета, рассмотрите статью, которую вы сейчас читаете. Где-то в недрах инфраструктуры KVERNER эта статья была отформатирована и представлена для публикации. Ему был присвоен URL-адрес, маршрутизированный по сети и прибывший на сервер. Сервер связал артефакт (статью) с URL-адресом и определил, что, когда запрос GET прибыл для этого URL-адреса, он вернул бы эту статью в HTML.

Когда вы создаете веб-приложение Java, вы создаете программное обеспечение, которое выполняется внутри Java-сервера. Приложение использует средства, предоставляемые контекстом сервера, и одним из этих средств является API-интерфейс Servlet. По этой причине сервер Java, который реализует спецификацию Servlet, иногда называют контейнером сервлета.

Чтобы создать сервлет, вы реализуете интерфейс Servlet и развертываете его внутри контейнера сервлета. На рисунке 3 показано, как ваше приложение использует сервлет.

Написание сервлетов с Tomcat

Теперь, когда у вас есть концептуальный обзор, давайте приступим к работе над написанием сервлета Java.

Первое, что вам понадобится, это контейнер сервлетов, иначе известный как сервер приложений Java. Tomcat и Jetty — два из самых популярных контейнеров сервлетов. Мы будем использовать Tomcat, потому что это один из самых давних серверов приложений для Java. Tomcat является бесплатным.

Читать еще:  Как поставить пароль на документ Word

Загрузите и установите Tomcat

Если у вас еще нет Tomcat, начните с открытия страницы загрузки Tomcat. Там вы можете выбрать либо установщик Windows, либо самую подходящую ZIP-версию для вашего компьютера.

Вот и все: вы только что добавили серверный уровень Java в свою операционную систему!

Проверить, работает ли Tomcat

Прежде чем идти дальше, давайте убедимся, что вы можете запустить Tomcat. Либо запустите службу Windows, либо запустите файл startup.sh или startup.bat из командной строки.

Теперь, когда Вы откроете веб-браузер и перейдете на localhost: 8080, вас следует приветствовать на следующем экране:

Запустите пример сервлета Tomcat

Теперь давайте посмотрим на сервлет Java. Удобно, Tomcat включил некоторые простые примеры.

Нажмите ссылку «Examples», которую вы видите в разделе «Developer Quick Start» на странице приветствия Tomcat. После того, нажмите ссылку «Servlet Examples».

Теперь вы можете увидеть простой сервлет в действии, щелкнув на «Выполнить» — Hello World.

Просмотр исходного кода сервлета

Нажмите стрелку «Назад» в своем браузере, затем щелкните ссылку источника для приложения HelloWorld. Источник показан в листинге 1.

Листинг 1. Исходный код для примера Hello World

Давайте рассмотрим этот код шаг за шагом.

Первая строка вызывает стандартный импорт Java . После этого программа определяет новый класс, который расширяет класс HttpServlet . Это важно, потому что сервлеты должны реализовывать интерфейс Servlet для запуска внутри контейнера сервлета.

Затем класс HelloWorld определяет метод, называемый doGet () . Это стандартный метод для сервлетов: он сообщает серверу направлять HTTP GET-запросы на этот метод. Другие HTTP-методы, такие как POST, обрабатываются аналогично называемыми методами, такими как doPost .

Обратите внимание, что doGet () имеет два параметра: (запрос HttpServletRequest , ответ HttpServletResponse ). Эти два объекта представляют собой запрос и ответ. Они обеспечивают доступ ко всему, что требуется вашему коду, чтобы справиться с запросом и выдать ответ. Например, в методе сервлетов HelloWorld.doGet объект ответа используется для информирования сервера о том, какой тип заголовка содержимого должен выдаваться. В этом случае это response.setContentType («text/html») ; .

Наконец, программа получает объект Java Writer из ответа response.getWriter () . Затем Writer используется для создания простого ответа HTML для возврата в браузер.

URL путь

Структура и поток кода в листинге 1 довольно интуитивно понятны, но есть вопиющее упущение. Как сервер знает, чтобы связать URL-адрес http://localhost:8080/examples/servlets/servlet/HelloWorldExample с методом HelloWorld.doGet?

Вы найдете ответ на эту тайну в метаданных приложения. Каждое веб-приложение Java включает в себя стандартный файл метаданных, называемый web.xml, который сообщает серверу, как сопоставлять URL-адреса сервлетам.

В примерах приложений Tomcat — WEB.xml находится в apache-tomcat-9.0.11webappsexamplesWEB-INFweb.xml.WEB-INFweb.xml — это стандартное расположение файла метаданных для сервлетов. Если вы откроете этот файл, вы увидите, как настроен сервер.

Сокращенный web.xml в листинге 2 содержит только ту информацию, которая нам нужна для нашего обсуждения.

Листинг 2. Исходный код для примера Tomcat — Hello World

В листинге 2 показан типичный заголовок XML-файла, ссылающийся на схему дескриптора веб-приложения Java. За этим следуют две записи: и .

Вызов назначает логическое имя HelloWorldExample классу HelloWorldExample через поля и .

Вызов присваивает этому логическому имени значение , тем самым связывая код с URL-адресом.

Другие возможности сервлета

Помимо сопоставления URL-адресов сервлеты предоставляют дополнительные возможности для фильтрации и аутентификации. Фильтры используются для обработки запросов, а аутентификация используется для назначения простых пользователей и ролей. Спецификация JavaServer Pages (JSP) обеспечивает поддержку для генерации HTML гораздо более мощным способом.

Заключение

Эта статья была концептуальным обзором сервлетов Java, включая обработку URL-адресов и обработку ответов внутри Java-сервера. Понимание этих основных элементов серверной Java-технологии поможет вам интегрировать более продвинутые концепции, такие как перенаправление серверов и отображение времени выполнения URL-адресов, которые являются новыми в Servlet 4.0.

Пакет java.net, ServerSocket

На сегодняшний день использование клиентов служб мгновенного обмена сообщениями (instant messanger) стало незаменимым средством для всех пользователей Интернета. Существует множество клиентов (Skype, WhatsApp, Viber, ICQ и т. д.), о которых каждый слышал и которые мы ежедневно используем. Все они работают по определенным правилам, т.е. реализуют определенные протоколы взаимодействия.

Наиболее распространенный протокол HTTP (Hyper Text Transfert Protocol) определяет взаимодействие двух программ, клиента и сервера, которые могут быть запущены на разных и удаленных друг от друга машинах. Клиентом является приложение, которое пользуется каким-то сервисом, предоставляемым сервером, обычно размещенном на удаленном компьютере. Клиент должен подключиться к удаленному серверу, который постоянно находится в режиме ожидания соединения. После этого они могут обмениваться информацией.

HTTP использует протокол TCP/IP. В статье рассмотриваются возможности, предоставляемые Java для работы с этим протоколом.

Распределение протоколов по уровням модели TCP/IP

Протокол HTTP располагается на прикладном уровне и использует для собственной реализации протоколы более низких уровней. Основой HTTP является протокол транспортного уровня TCP.

Согласно протоколу IP (Internet Packet), каждый узел (компьютер, switch и т.п.) в сети имеет свой IP-адрес. На данный момент интернет работает по протоколу IPv4, где IP адрес записывается 4 числами от 0 до 255 – например, 127.0.0.1. Существует и другой способ идентификации компьютеров в сети через доменное имя, которое более удобное и нагляднее идентифицирует компьютер, чем простой набор чисел (например, java-oline.ru). В Интернете существуют специальные сервера DNS (Domain Name System), которые осуществляют преобразование доменного имени в IP-адрес и наоборот.

TCP протокол базируется на IP для доставки пакетов, но добавляет два важных свойства :

  • установление соединения между приложениями;
  • использование портов, а не просто узлов.

Таким образом, для идентификации компьютера (host’a) в сети используется IP-адрес; для идентификации приложения TCP добавляет понятие порта. Порт – это целое число от 1 до 65535 указывающее, какому приложению предназначается пакет.

Java для работы в сети имеет специальный пакет java.net, содержащий класс Socket, что в переводе означает «гнездо». Ключевыми классами для реализации взаимодействия программ по протоколу TCP являются :

  • java.net.ServerSocket – класс реализует серверный сокет, который ожидает запросы, приходящие от клиентов по сети, и может отправлять ответ.
  • java.net.Socket – класс реализует клиентский сокет.

Серверный сокет ServerSocket

Для создания серверного сокета ServerSocket можно использовать один из следующих конструкторов :

Первым параметров в конструктор необходимо передать порт port, который будет привязан к серверному сокету. Если порт занят или запрещён к использованию политикой безопасности компьютера, то вызывается исключение IOException. Если значение передавамого порта равно 0, то система сама выделит номер свободного порта. Значение полученного порта можно узнать через вызов функции getLocalPort(). Несвязанный серверный сокет ServerSocket() необходимо «связывать» с IP-адресом и портом (см. ниже метод bind).

Параметр backlog устанавливает максимальное количество клиентских подключений. Если количество подключений достигло предела, то следующему клиенту в подключении будет отказано.

Для работы с IP-адресами в библиотеке Java имеется класс java.net.InetAddress, который используется в третьем конструкторе ServerSocket. С помощью InetAddress можно определить адрес IP локального узла, а также адреса удаленного узла, заданного доменным именем. Наиболее распространенные методы класса InetAddress :

При разработке сетевых приложений на начальном этапе, как правило, используют один компьютер (host). Для этого создатели протокола IP определили специальный адрес, называемый localhost – это IP-адрес “локальной заглушки (local loopback)” для работы приложений без использования сети. Общий порядок получения этого адреса в Java следующий :

Если методу getByName() передать значение null, то по умолчанию будет использоваться localhost. Cодержимым InetAddress нельзя манипулировать. Для создания InetArddress можно использовать один из перегруженных статических методов класса getByName(), getAllByName() или getLocalHost().

Методы серверного сокета

В таблице представлены наиболее часто используемые методы серверного сокета ServerSocket.

Программирование сокетов на Java

[Disclaimer: Данная статья была переведена в рамках “Конкурса на лучший перевод статьи” на сервисе Quizful. Ссылка на оригинал находится внизу страницы.]

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

Читать еще:  Сети для Самых Маленьких. Микровыпуск №5. FAQ по сетевым технологиям

Что такое сокет?

На сегодняшний день использование клиентов служб мгновенного обмена сообщениями (instant messanger) стало незаменимым средством для всех пользователей Интернета. Существует множество различных протоколов и клиентов (MSN, ICQ, Skype и т. д.), о которых каждый слышал и которые мы все ежедневно используем. Но не все знают, что положено в основу их роботы – собственно для этого статья и написана. Предположим, вы установили один из клиентов служб мгновенного обмена сообщениями на ваш компьютер. После его запуска и введения имени и пароля вашего пользователя, программа пытается подключиться к серверу. Что именно означает слово “подключиться”?

Каждый компьютер в сети имеет IP-адрес. Этот адрес похож на ваш домашний адрес – он однозначно идентифицирует ваш компьютер и позволяет другим общаться с вашим компьютером. Не будем вдаваться в подробности IP-адреса, так как эта статья не о них, хочу только отметить что IP-адрес это набор номеров разделенных точками (например, 64.104.137.158). Хотя существует и другой способ идентификации компьютеров в сети – доменное имя, которое более удобное и нагляднее идентифицирует компьютер, чем простой набор чисел (например, www.quizful.net). В Интернете существуют специальные компьютеры, которые осуществляют преобразование доменного имени в IP-адрес и наоборот.

На одном компьютере может параллельно исполняется несколько программ. Предположим, что вы запустили 10 программ на своем компьютере, и все они ожидают, чтоб другие компьютеры связались с ними. Можете представить себе это так: вас 10 человек в большом офисе с 1 телефоном и все ждут звонков от их собственных клиентов. Как вы это решите? Можно конечно назначить ответственного работника, и он будет приносить телефон соответственному человеку, которому звонят, но тогда другие клиенты не смогут дозвониться к другим людям. Кроме того, это очень трудно и нелепо иметь ответственного работника за маршрутизацию звонков к нужным людям. Вы должно быть, уже догадались, к чему я веду – если все эти программы, исполняющиеся на одном компьютере, с гордостью просят своих клиентов связаться с ними по определенному IP-адресу, то их клиенты не будут довольны. Идея состоит в следующем … иметь отдельный IP-адрес для каждой программы, верно? НЕ ВЕРНО! Суть вопроса не правильная – это также как спрашивать об отдельном офисе для каждого из вас. Ну, тогда … может отдельных телефонных номеров будет достаточно? ДА! На сетевом жаргоне “отдельные телефонные номера” имеют название порты. Порт – это просто число и каждая из программ, которая исполняется на определенном компьютере, может выбрать уникальное число порта, чтоб определить себя для внешнего мира. ЗАПОМНИТЕ – эти порты вы не сможете найти среди аппаратных средств компьютера (даже не старайтесь их искать). Эти числа – логические. Теперь все прояснилось: существует IP-адрес, с помощью которого другие компьютеры могут распознавать определенный компьютер в сети, и порт-число, которое определяет некую программу, работающую на компьютере. Также становиться понятным и то, что две программы на разных компьютерах могут использовать один и тот же порт (два дома на разных улицах тоже могут иметь один и тот самый номер, или нет?). Ну что же, мы практически у цели, только чтоб немного вас попугать, давайте выведем формулу:

Если сложить вместе выше описанные уравнения, то получим:

Если вы догадались до этого сами – значит мои усилия не пропали зря. Если нет, тогда прочитайте еще раз все сначала или воспользуйтесь Google для поиска лучшей статьи.

Подведем итог, сокет – это комбинация IP-адреса и порта. Сокет адрес надает возможность другим компьютерам в сети находить определенную программу, которая исполняется на определенном компьютере. Вы можете отображать сокет адрес вот так 64.104.137.58:80, где 64.104.137.58 – IP-адрес и 80 – порт.

Как программировать с использованием сокетов?

Достаточно о теории, давайте перейдем к действиям. Разработаем очень простой и наглядный код на Java, который продемонстрирует возможности использования сокетов. Попробуем реализовать следующий список действий:

1) Одна Джава программа будет пытаться связаться с другой Java программой (которая отчаянно ждет кого-то, чтоб с ней связался). Назовем первую программу Клиентом, а вторую Сервером.

2) После успешного связывания с сервером, клиент ждет ввода данных от вас и отсылает текст серверу.

3) Серверная программа отсылает клиенту назад тот ;t текст (для того чтоб показать, что она умеет делать даже такое полезное действие).

4) Полученный от сервера текст, клиент показывает вам, чтоб показать вам мнение сервера о вас. Приготовились приступить к разработке? Начнем. Отмечу только, что я не буду учить вас программированию на Java с чистого листа, а только объясню код, который относится к сокетам. Создайте 2 новых Джава программы и назовите их Server.java и Client.java. Я привел код ниже, только не пугайтесь, я все объясню.

Теперь скомпилируем код:

Откроем два командных окна (DOS). В одном окне введем:

Обязательно в таком порядке.

Теперь введите строку текста в окне, где запущен клиент, и нажмите кнопку Enter. Наблюдайте за двумя окнами и увидите что случиься. В конце, нажмите Ctrl-C для того чтоб остановить программы.

Объяснение кода работы с сокетами

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

Рассмотрим следующую часть кода сервера:

Класс ServerSocket немного отличается от класса Socket. Класс Socket – это и есть сокет. Главное отличие ServerSocket заключается в том, что он умеет заставлять программу ждать подключений от клиентов. Когда вы его создаете, нужно указывать порт, с которым он будет работать, и вызвать его метод accept(). Этот метод заставляет программу ждать подключений по указанному порту. Исполнение программы зависает в этом месте, пока клиент не подключится. После успешного подключения клиентом, создается нормальный Socket объект, который вы можете использовать для выполнения все существующий операций с сокетом. Заметим также, что этот Socket объект отображает другой конец соединения. Если вы хотите отослать данные клиенту, то вы не можете использовать для этого ваш собственный сокет.

Следующим рассмотрим Socket класс. Вы можете создать Socket объект, указав IP-адрес и порт. Вы можете использовать InetAddress класс для отображения IP-адреса (этот способ более предпочтительный). Для создания InetAddress объекта используйте следующий метод:

Заметим, что в нашей программе мы использовали адрес 127.0.0.1. Это специальный адрес называется адрес замыкания – он просто отображает локальный компьютер. Если вы намерены запустить клиент и сервер на разных компьютерах, тогда нужно использовать соответственный IP-адрес сервера.

После того как мы создали InetAddress, то можно создать Socket:

После создания Socket объекта, можно взять входной и выходной потоки сокета. Входной поток позволит вам читать с сокета, а выходной поток дает возможность писать в сокет.

Следующие строки просто конвертируют потоки в другие типы потоков. После этого нам легче будет работать с String объектами. Этот код ничего не делает с сетью.

Все остальное очень просто – простые манипуляции с объектами потоков (никаких сокетов). Вы можете использовать ваши любимые потоки, вызывать ваши любимые методы, и удостоверяться в передаче данных во второй конец. Если вы не очень осведомлены в использовании потоков, рекомендую вам найти статью о них и прочесть.

Если Вам понравилась статья, проголосуйте за нее

Голосов: 85 Голосовать

голоса
Рейтинг статьи
Ссылка на основную публикацию
Статьи c упоминанием слов: