воскресенье, 17 февраля 2013 г.

фильтры ebs анимация

Это была моя первая личная победа над сложной задачей реализации WebSocket сервера, хоть я использовал документацию Netty, кроме этого я так же читал другие ресурсы (в том числе хабр). Надеюсь, что теперь любой желающий сможет сделать свой WebSocket сервер на Java с использованием Netty.

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

String clietnMsg = ((TextWebSocketFrame) frame).getText();

Обуславливаем это тем, что браузер присылает методом GET на наш WEBSOCKET_PATH заголовок Upgrade: websocket. Далее начинается процесс приветствия (handshake), который сам отправляет клиенту верные заголовки и в итоге переключает протокол с http на ws открывая постоянное соединение. В документации метод handleWebSocketFrame проверяет не закрыто ли соединение, отвечает на пакет ping и проверяет текст ли пришел, после чего возвращает принятую строку назад клиенту. Получаем строчку, которую прислал клиент:

if(req.getMethod() == GET && req.getUri().equals(WEBSOCKET_PATH) && Values.UPGRADE.equalsIgnoreCase(req.getHeader(CONNECTION)) && WEBSOCKET.equalsIgnoreCase(req.getHeader(Names.UPGRADE))) { WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory(getWebSocketLocation(req), null, false); handshaker = wsFactory.newHandshaker(req); if(handshaker == null){ wsFactory.sendUnsupportedWebSocketVersionResponse(ctx.getChannel()); }else{ handshaker.handshake(ctx.getChannel(), req).addListener(WebSocketServerHandshaker.HANDSHAKE_LISTENER); } return; } //Здесь должен быть ответ с ошибкой HTTP_VERSION_NO....

Обрабатывать запрос на подключение ws будем примерно так:

sendHttpResponse(ctx, req, new DefaultHttpResponse(HTTP_1_1, HTTP_VERSION_NOT_SUPPORTED));

Метод handleHttpRequest должен корректно подключать клиентов по протоколу websocket и только через GET, а так же отбрасывать всех любопытных по http, показывая им ошибку, например "505 HTTP Version Not Supported".

if (msg instanceof HttpRequest) { handleHttpRequest(ctx, (HttpRequest) msg); }else if (msg instanceof WebSocketFrame) { handleWebSocketFrame(ctx, (WebSocketFrame) msg); }

В документации Netty используется Executors.newCachedThreadPool(), он зачем-то поднимает аж 9 потоков выполнения, как по мне это неоправданная трата ресурса. Я решил ограничиться 3мя потоками и использовал OrderedMemoryAwareThreadPoolExecutor(). Затем необходимо обрабатывать подключения и пакеты, для этого назначаются (см. документацию как, класс WebSocketServerPipelineFactory) четыре обработчика, три из них стандартные из пакетов Netty (HttpRequestDecoder, HttpChunkAggregator, HttpResponseEncoder) и один мы должны описать самостоятельно. Обработчик WebSocketServerHandler наследуется от класса SimpleChannelUpstreamHandler из Netty. Необходимо переопределить метод messageReceived под нужды, а нужды таковы: 1) Обрабатывать запросы по протоколу http:// 2) Обрабатывать запросы по протоколу ws:// Для сего пишем следующее:

ExecutorService bossExec = new OrderedMemoryAwareThreadPoolExecutor(1, 400000000, 2000000000, 60, TimeUnit.SECONDS); ExecutorService ioExec = new OrderedMemoryAwareThreadPoolExecutor(3, 400000000, 2000000000, 60, TimeUnit.SECONDS); ServerBootstrap networkServer = new ServerBootstrap(new NioServerSocketChannelFactory(bossExec, ioExec, 3)); networkServer.setOption("connectTimeoutMillis", 10000); networkServer.setPipelineFactory(new WebSocketServerPipelineFactory()); Channel channel = networkServer.bind(new InetSocketAddress(address, port));

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

Раз нет, значит будет

Потратив некоторое время на поиски готовых решений в гугл’е, я понял, что есть несколько способов реализации поставленной задачи при использовании сервлетов: 1) JWebSocket 2) Jetty ( Вы можете посмотреть решение тут: ) 3) Netty Я не буду говорить ничего о JWebSocket, потому что я не смог с ним разобраться (да и не хотелось, странный он, не верю я ему). Готовое решение на Jetty, с хабра, было бы очень кстати, если бы не устарело, по видимому разработчики решили что-то с чем-то объединить и нужные классы оказались перемещены/переименованы/удалены (нужное подчеркнуть). Надо сказать, что Java для меня очень новый язык и после таких языков как js и php давался мне давольно легко. В общем-то это мой первый опыт использования языка, не для создания окошек с кнопочками, полями и ‘Hello World’, а для чего-то более серьёзного и сложного.

Может есть что-то готовое?

Здравствуйте. Некоторое время назад я решил сделать своё web-приложение которое должно быстро обмениваться данными с сервером. Вопрос был о том, как же сделать качественную и быструю скорость передачи данных между web-приложением и сервером. Можно было бы использовать Flash но я не стал, т.к. моё web-приложение должно корректно запускаться на iДевайсах. Тогда мой взор упал на long-polling, проведя несколько тестов, я понял, что драгоценные секунды теряются на открытие нового соединения и ожидание ответа от сервера. Немного позже я узнал, совершенно случайно, что есть еще некий WebSocket, который как раз решил бы все мои проблемы с передачей данных. Пост про маленькую победу над сложной задачей.

Опубликовано автором

Навигация по записям

Ещё одна копия хабора

SavePearlHarbor | Ещё одна копия хабора | Страница 196

Комментариев нет:

Отправить комментарий