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

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

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

четверг, марта 03, 2016

Understanding NIO2.0 Asynchronous I/O. EchoServer

Посмотрим внимательно на NIO2.0 асинхронную сокетную модель появившуюся еще в Java 7 и напишем полностью асинхронный сервер и клиент по типу request/reply.
Асинхронный IO для сокетного взаимодействия представлен следующими классами:
  • AsynchronousSocketChannel
  • AsynchronousServerSocketChannel
Есть два подхода работы с ними. Используя:
  • Future
  • CompletionHandler
Использование Future предполагает следующие действия
  • Использование блокирующего вызова get(), который сразу вернет результат
    AsynchronousSocketChannel worker = future.get();
  • Проверка результата выполнения
    while(!future.isDone()) {
     // do something
            Thread.sleep(100);
    }
Работа с Future моделью в любом случае предполагает блокировку потока выполнения. Я вообще не вижу смысла в таком случае в использовании асинхронного IO. Какой в смысл, если в результате у нас все равно возникают блокировки, и при этом нужно будет выносить процессинг в отдельный поток. Такое может понадобиться только в самых простых случаях.

Очевидно что для полного асинхронного взаимодействия надо использовать CompletionHandler. При этом надо действовать аккуратно чтобы не свалиться calback hell.