Показаны сообщения с ярлыком WebSocket. Показать все сообщения
Показаны сообщения с ярлыком WebSocket. Показать все сообщения

пятница, марта 11, 2016

WebSocket server java. Best way

Итак, когда мы разобрались как реализовать WebSocket server с использованием NIO2.0. Я покажу лучший способ это сделать используя JSR 356, Java API for WebSocket. Обратите внимание насколько все просто. Достаточно обвесить обычный POJO следующими анатациями и упаковать как веб-приложение.
  • @ServerEndpoint
  • @OnOpen
  • @OnMessage
  • @OnClose
  • @OnError
Все! Это настолько просто, что даже не требует пояснений.
Код как обычно на https://github.com/Hibernate2009/websocket-jsr356.git

package com.bssys.ws;

import java.util.logging.Logger;

import javax.websocket.CloseReason;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;


@ServerEndpoint("/echo")
public class WsChatServlet {
 private Logger logger = Logger.getLogger(this.getClass().getName());
  
    @OnOpen
    public void onOpen(Session session) {
        logger.info("Connected ... " + session.getId());
        SessionManager.getInstance().addSession(session);
    }
 
    @OnMessage
    public void onMessage(Session session, String message ) {
     logger.info(String.format("Client %s send message %s", session.getId(), message));
     SessionManager.getInstance().writeMessageToClients(session, message);
    }
 
    @OnClose
    public void onClose(Session session, CloseReason closeReason) {
        logger.info(String.format("Session %s closed because of %s", session.getId(), closeReason));
        SessionManager.getInstance().removeSession(session);
    }
    
    @OnError
    public void onError(Session session, Throwable throwable){
     logger.info(String.format("Session %s error ", session.getId()));
     SessionManager.getInstance().removeSession(session);
    }
}

NIO2.0 Asynchronous I/O. WebSocket chat server

Для лучшего понимания NIO2.0 есть очень подходящая задача. А именно попробуем реализовать WebSocket chat server. В качестве клиента будет выступать браузер. Если кратко с помощью WebSocket можно создать двунаправленый канал связи, в частности между браузером и сервером. Клиент в общем может быть любым, главное чтобы он поддерживал нужный протокол.

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

GET / HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Host: 127.0.0.1
Origin: null
Sec-WebSocket-Key: tR+4GeaXR7PuLsQtvlsMTw==
Sec-WebSocket-Version: 13
Sec-WebSocket-Extensions: x-webkit-deflate-frame
Если сервер поддерживает websocket ответит следующим образом
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: ELY6l2B3+S/6vjfrkzFMurz/hhQ=
Браузер при этом оставляет открытым соединение. Что позволяет отправлять и получать данные в любое время.
Важную часть при установлении рукопожатия составляет обмен ключами. Особой магии тут нет.

  • Клиент посылает ключ в заголовке Sec-WebSocket-Key закодированный в base64.
  • Серверу нужно взять этот ключ добавить "магическую строку" 258EAFA5-E914-47DA-95CA-C5AB0DC85B11 и построить по итоговой строке SHA-1 хеш, и передать его в заголовке ответа Sec-WebSocket-Accept