java jetty websocket_转 Jetty9 & WebSocket

Creating WebSockets in Jetty is even easier with Jetty 9!

While the networking gurus in Jetty have been working on the awesome improvements to the I/O layers in core Jetty 9, the WebSocket fanatics in the community have been working on making writing WebSockets even easier.

The initial WebSocket implementation in Jetty was started back in November of 2009, well before the WebSocket protocol was finalized.

It has grown in response to Jetty’s involvement with the WebSocket draft discussions to the finalization of RFC6455, and onwards into the changes being influenced on our design as a result of WebSocket extensions drafts such as x-webkit-perframe-deflate, permessage-deflate, fragment, andongoing mux discussions.

The Jetty 7.x and Jetty 8.x codebases provided WebSockets to developers required a complex set of knowledge about how WebSockets work and how Jetty implemented WebSockets.  This complexity was as a result of this rather organic growth of WebSocket knowledge around intermediaries and WebSocket Extensions impacted the original design.

With Jetty 9.x we were given an opportunity to correct our mistakes.

The new WebSockets API in Jetty 9.x

Note: this information represents what is in the jetty-9 branch on git, which has changed in small but important ways since 9.0.0.M0 was released.

With the growing interest in next generation protocols like SPDY and HTTP/2.0, along with evolving standards being tracked for Servlet API 3.1 and Java API for WebSockets (JSR-356), the time Jetty 9.x was at hand.  We dove head first into cleaning up the codebase, performing some needed refactoring, and upgrading the codebase to Java 7.

Along the way, Jetty 9.x started to shed the old blocking I/O layers, and all of the nasty logic surrounding it, resulting on a Async I/O focused Jetty core.  We love this new layer, and we expect you will to, even if you don’t see it directly.  This change benefits Jetty with a smaller / cleaner / easier to maintain and test codebase, along with various performance improvements such as speed, CPU use, and even less memory use.

In parallel, the Jetty WebSocket codebase changed to soak up the knowledge gained in our early adoption of WebSockets and also to utilize the benefits of the new Jetty Async I/O layers better.   It is important to note that Jetty 9.x WebSockets is NOT backward compatible with prior Jetty versions.

The most significant changes:Requires Java 7

Only supporting WebSocket version 13 (RFC-6455)

Artifact Split

The monolithic jetty-websocket artifact has been to split up the various websocket artifacts so that developers can pick and choose what’s important to them.

The new artifacts are all under the org.eclipse.jetty.websocket groupId on maven central.websocket-core.jar – where the basic API classes reside, plus internal implementation details that are common between server & client.

websocket-server.jar – the server specific classes

websocket-client.jar – the client specific classesOnly 1 Listener now (WebSocketListener)

Now Supports Annotated WebSocket classes

Focus is on Messages not Frames

In our prior WebSocket API we assumed, incorrectly, that developers would want to work with the raw WebSocket framing.   This change brings us in line with how every other WebSocket API behaves, working with messages, not frames.WebSocketServlet only configures for a WebSocketCreator

This subtle change means that the Servlet no longer creates websockets of its own, and instead this work is done by the WebSocketCreator of your choice (don’t worry, there is a default creator).

This is important to properly support the mux extensions and future Java API for WebSockets (JSR-356)

Jetty 9.x WebSockets Quick Start:

Before we get started, some important WebSocket Basics & GotchasA WebSocket Frame is the most fundamental part of the protocol, however it is not really the best way to read/write to websockets.

A WebSocket Message can be 1 or more frames, this is the model of interaction with a WebSocket in Jetty 9.x

A WebSocket TEXT Message can only ever be UTF-8 encoded. (it you need other forms of encoding, use a BINARY Message)

A WebSocket BINARY Message can be anything that will fit in a byte array.

Use the WebSocketPolicy (available in the WebSocketServerFactory) to configure some constraints on what the maximum text and binary message size should be for your socket (to prevent clients from sending massive messages or frames)

First, we need the servlet to provide the glue.

We’ll be overriding the configure(WebSocketServerFactory) here to configure a basic MyEchoSocket to run when an incoming request to upgrade occurs.package examples; import org.eclipse.jetty.websocket.server.WebSocketServerFactory; import org.eclipse.jetty.websocket.server.WebSocketServlet; public class MyEchoServlet extends WebSocketServlet { @Override public void configure(WebSocketServerFactory factory) { // register a socket class as default factory.register(MyEchoSocket.class); } }

The responsibility of your WebSocketServlet class is to configure theWebSocketServerFactory.     The most important aspect is describing how WebSocket implementations are to be created when request for new sockets arrive.  This is accomplished by configuring an appropriate WebSocketCreator object.  In the above example, the default WebSocketCreator is being used to register a specific class to instantiate on each new incoming Upgrade request.

If you wish to use your own WebSocketCreator implementation, you can provide it during this configure step.

Note that request for new websockets can arrive from a number of different code paths, not all of which will result in your WebSocketServlet being executed.  Mux for example will result in a new WebSocket request arriving as a logic channel within the MuxExtension itself.

As for implementing the MyEchoSocket, you have 3 choices.Implementing Listener

Using an Adapter

Using Annotations

Choice 1: implementing WebSocketListener interface.

Implementing WebSocketListener is the oldest and most fundamental approach available to you for working with WebSocket in a traditional listener approach (be sure you read the other approaches below before you settle on this approach).It is your responsibility to handle the connection open/close events appropriately when using the WebSocketListener. Once you obtain a reference to the WebSocketConnection, you have a variety of NIO/Async based write() methods to write content back out the connection.package examples; import java.io.IOException; import org.eclipse.jetty.util.Callback; import org.eclipse.jetty.util.FutureCallback; import org.eclipse.jetty.websocket.core.api.WebSocketConnection; import org.eclipse.jetty.websocket.core.api.WebSocketException; import org.eclipse.jetty.websocket.core.api.WebSocketListener; public class MyEchoSocket implements WebSocketListener { private WebSocketConnection outbound; @Override public void onWebSocketBinary(byte[] payload, int offset, int len) { /* only interested in text messages */ } @Override public void onWebSocketClose(int statusCode, String reason) { this.outbound = null; } @Override public void onWebSocketConnect(WebSocketConnection connection) { this.outbound = connection; } @Override public void onWebSocketException(WebSocketException error) { error.printStackTrace(); } @Override public void onWebSocketText(String message) { if (outbound == null) { return; } try { String context = null; Callback callback = new FutureCallback<>(); outbound.write(context,callback,message); } catch (IOException e) { e.printStackTrace(); } } }

Choice 2: extending from WebSocketAdapter

Using the provided WebSocketAdapter, the management of the Connection is handled for you, and access to a simplified WebSocketBlockingConnection is also available (as well as using the NIO based write signature seen above)package examples; import java.io.IOException; import org.eclipse.jetty.websocket.core.api.WebSocketAdapter; public class MyEchoSocket extends WebSocketAdapter { @Override public void onWebSocketText(String message) { if (isNotConnected()) { return; } try { // echo the data back getBlockingConnection().write(message); } catch (IOException e) { e.printStackTrace(); } } }

Choice 3: decorating your POJO with @WebSocket annotations.

This the easiest WebSocket you can create, and you have some flexibility in the parameters of the methods as well.package examples; import java.io.IOException; import org.eclipse.jetty.util.FutureCallback; import org.eclipse.jetty.websocket.core.annotations.OnWebSocketMessage; import org.eclipse.jetty.websocket.core.annotations.WebSocket; import org.eclipse.jetty.websocket.core.api.WebSocketConnection; @WebSocket(maxTextSize = 64 * 1024) public class MyEchoSocket { @OnWebSocketMessage public void onText(WebSocketConnection conn, String message) { if (conn.isOpen()) { return; } try { conn.write(null,new FutureCallback(),message); } catch (IOException e) { e.printStackTrace(); } } }

The annotations you have available:@OnWebSocketMessage: To receive websocket message events.

Examples:@OnWebSocketMessage public void onTextMethod(String message) { // simple TEXT message received } @OnWebSocketMessage public void onTextMethod(WebSocketConnection connection, String message) { // simple TEXT message received, with Connection // that it occurred on. } @OnWebSocketMessage public void onBinaryMethod(byte data[], int offset, int length) { // simple BINARY message received } @OnWebSocketMessage public void onBinaryMethod(WebSocketConnection connection, byte data[], int offset, int length) { // simple BINARY message received, with Connection // that it occurred on. }

@OnWebSocketConnect: To receive websocket connection connected event (will only occur once).

Example:@OnWebSocketConnect public void onConnect(WebSocketConnection connection) { // WebSocket is now connected }

@OnWebSocketClose: To receive websocket connection closed events (will only occur once).

Example:@OnWebSocketClose public void onClose(int statusCode, String reason) { // WebSocket is now disconnected } @OnWebSocketClose public void onClose(WebSocketConnection connection, int statusCode, String reason) { // WebSocket is now disconnected }

@OnWebSocketFrame: To receive websocket framing events (read only access to the rawFrame details).

Example:@OnWebSocketFrame public void onFrame(Frame frame) { // WebSocket frame received } @OnWebSocketFrame public void onFrame(WebSocketConnection connection, Frame frame) { // WebSocket frame received }

One More Thing … The Future

We aren’t done with our changes to Jetty 9.x and the WebSocket API, we are actively working on the following features as well…Mux Extension

The multiplex extension being drafted will allow for multiple virtual WebSocket connections over a single physical TCP/IP connection.  This extension will allow browsers to better utilize their connection limits/counts, and allow web proxy intermediaries to bundle multiple websocket connections to a server together over a single physical connection.Streaming APIs

There has been some expressed interest in providing read and write of text or binary messages using the standard Java IO Writer/Reader (for TEXT messages) and OutputStream/InputStream (for BINARY messages) APIs.

Current plans for streamed reading includes new @OnWebSocketMessage interface patterns.// In the near future, we will have the following some Streaming // forms also available. This is a delicate thing to // implement and currently does not work properly, but is // scheduled. @OnWebSocketMessage public void onTextMethod(Reader stream) { // TEXT message received, and reported to your socket as a // Reader. (can handle 1 message, regardless of size or // number of frames) } @OnWebSocketMessage public void onTextMethod(WebSocketConnection connection, Reader stream) { // TEXT message received, and reported to your socket as a // Reader. (can handle 1 message, regardless of size or // number of frames). Connection that message occurs // on is reported as well. } @OnWebSocketMessage public void onBinaryMethod(InputStream stream) { // BINARY message received, and reported to your socket // as a InputStream. (can handle 1 message, regardless // of size or number of frames). } @OnWebSocketMessage public void onBinaryMethod(WebSocketConnection connection, InputStream stream) { // BINARY message received, and reported to your socket // as a InputStream. (can handle 1 message, regardless // of size or number of frames). Connection that // message occurs on is reported as well. }

And for streaming writes, we plan to provide Writer and OutputStream implementations that simply wrap the provided WebSocketConnection.Android Compatible Client Library

While Android is currently not Java 7 compatible, a modified websocket-client library suitable for use with Android is on our TODO list.Support Java API for WebSocket API (JSR356)

We are actively tracking the work being done with this JSR group, it is coming, but is still some way off from being a complete and finished API (heck, the current EDR still doesn’t support extensions). Jetty 9.x will definitely support it, and we have tried to build our Jetty 9.x WebSocket API so that the the Java API for WebSockets can live above it.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值