Клиент Java для API WebSockets

Клиент Java для API WebSockets

1. Вступление

HTTP (протокол передачи гипертекста) - это протокол запроса-ответа без сохранения состояния. Его простая конструкция делает его очень масштабируемым, но непригодным и неэффективным для высокоинтерактивных веб-приложений реального времени из-за объема служебных данных, которые необходимо передавать вместе с каждым запросом / ответом.

Поскольку HTTP является синхронным, а приложения реального времени должны быть асинхронными, любые решения, такие как опрос или длинный опрос (Comet), имеют тенденцию быть сложными и неэффективными.

Для решения указанной выше проблемы нам нужен основанный на стандартах, двунаправленный и полнодуплексный протокол, который может использоваться как серверами, так и клиентами, и это привело к введениюJSR 356 API - в этой статье, мы покажем пример его использования.

2. Настроить

Давайте включим в наш проект зависимости Spring WebSocket:


    org.springframework
    spring-websocket
    5.0.5.RELEASE
 
 
    org.springframework
    spring-messaging
    5.0.5.RELEASE
 

Мы всегда можем получить последние версии зависимостей от Maven Central дляspring-websocket иspring-messaging.

3. ТОПАЙТЕ

Протокол потоковой передачи текстовых сообщений (STOMP) - это простой, совместимый проводной формат, который позволяет клиенту и серверам связываться практически со всеми брокерами сообщений. Это альтернатива AMQP (расширенный протокол очереди сообщений) и JMS (служба сообщений Java).

STOMP определяет протокол для связи клиент / сервер, используя семантику обмена сообщениями. Семантика находится над WebSockets и определяет фреймы, которые отображаются на фреймы WebSockets.

Использование STOMP дает нам гибкость в разработке клиентов и серверов на разных языках программирования. В этом текущем примере мы будем использовать STOMP для обмена сообщениями между клиентом и сервером.

4. WebSocket Server

Вы можете узнать больше о создании серверов WebSocket в этомarticle.

5. Клиент WebSocket

Для связи с сервером WebSocket клиент должен инициировать соединение WebSocket, отправив HTTP-запрос на сервер с правильно установленным заголовкомUpgrade:

GET ws://websocket.example.com/ HTTP/1.1
Origin: http://example.com
Connection: Upgrade
Host: websocket.example.com
Upgrade: websocket

Обратите внимание, что URL-адреса WebSocket используют схемыws иwss, вторая означает безопасные WebSockets.

Сервер отвечает, отправляя заголовокUpgrade в ответе, если включена поддержка WebSockets.

HTTP/1.1 101 WebSocket Protocol Handshake
Date: Wed, 16 Oct 2013 10:07:34 GMT
Connection: Upgrade
Upgrade: WebSocket

После завершения этого процесса (также известного как рукопожатие WebSocket) исходное соединение HTTP заменяется соединением WebSocket поверх одного и того же соединения TCP / IP, после чего любая из сторон может обмениваться данными.

Это клиентское соединение инициируется экземпляромWebSocketStompClient.

5.1. WebSocketStompClient

Как описано в разделе 3, нам сначала нужно установить соединение WebSocket, и это делается с помощью классаWebSocketClient.

WebSocketClient можно настроить с помощью:

  • StandardWebSocketClient предоставляется любой реализацией JSR-356, такой как Tyrus

  • JettyWebSocketClient предоставляется собственным API WebSocket Jetty 9+

  • Любая реализация SpringWebSocketClient

Мы будем использоватьStandardWebSocketClient, реализациюWebSocketClient в нашем примере:

WebSocketClient client = new StandardWebSocketClient();

WebSocketStompClient stompClient = new WebSocketStompClient(client);
stompClient.setMessageConverter(new MappingJackson2MessageConverter());

StompSessionHandler sessionHandler = new MyStompSessionHandler();
stompClient.connect(URL, sessionHandler);

new Scanner(System.in).nextLine(); // Don't close immediately.

По умолчаниюWebSocketStompClient поддерживаетSimpleMessageConverter. Поскольку мы имеем дело с сообщениями JSON, мы устанавливаем конвертер сообщений наMappingJackson2MessageConverter, чтобы преобразовать полезную нагрузку JSON в объект.

При подключении к конечной точке мы передаем экземплярStompSessionHandler, который обрабатывает такие события, какafterConnected иhandleFrame.

Если наш сервер поддерживает SockJs, то мы можем изменить клиент, чтобы использоватьSockJsClient вместоStandardWebSocketClient.

5.2. StompSessionHandler

Мы можем использоватьStompSession для подписки на тему WebSocket. Это можно сделать, создав экземплярStompSessionHandlerAdapter, который, в свою очередь, реализуетStompSessionHandler.

StompSessionHandler предоставляет события жизненного цикла для сеанса STOMP. События включают обратный вызов, когда сеанс установлен, и уведомления в случае сбоев.

Как только клиент WebSocket подключается к конечной точке,StompSessionHandler уведомляется и вызывается методafterConnected(), в котором мы используемStompSession для подписки на тему:

@Override
public void afterConnected(
  StompSession session, StompHeaders connectedHeaders) {
    session.subscribe("/topic/messages", this);
    session.send("/app/chat", getSampleMessage());
}
@Override
public void handleFrame(StompHeaders headers, Object payload) {
    Message msg = (Message) payload;
    logger.info("Received : " + msg.getText()+ " from : " + msg.getFrom());
}

Убедитесь, что сервер WebSocket работает и работает клиент, сообщение будет отображаться на консоли:

INFO o.b.w.client.MyStompSessionHandler - New session established : 53b993eb-7ad6-4470-dd80-c4cfdab7f2ba
INFO o.b.w.client.MyStompSessionHandler - Subscribed to /topic/messages
INFO o.b.w.client.MyStompSessionHandler - Message sent to websocket server
INFO o.b.w.client.MyStompSessionHandler - Received : Howdy!! from : Nicky

6. Заключение

В этом кратком руководстве мы реализовали клиент WebSocket на основе Spring.

Полную реализацию можно найтиover on GitHub.