Notes on WebSockets and Atmosphere Created 04/20/14 Updated 06/12/14, Updated 10/29/14, Updated 01/17/15, Updated 01/29/15, Updated 02/26/15 Introduction to WebSockets WebSocket is a protocol providing full-duplex communications channels over a single TCP connection. The WebSocket protocol was standardized by the IETF as RFC 6455 in 2011, and the WebSocket API in Web IDL is being standardized by the W3C. WebSocket is designed to be implemented in web browsers and web servers, but it can be used by any client or server application. The WebSocket Protocol is an independent TCP-based protocol. Its only relationship to HTTP is that its handshake is interpreted by HTTP servers as an Upgrade request. The WebSocket protocol makes more interaction between a browser and a web site possible, facilitating live content and the creation of real-time games. This is made possible by providing a standardized way for the server to send content to the browser without being solicited by the client, and allowing for messages to be passed back and forth while keeping the connection open. In this way a twoway (bi-directional) ongoing conversation can take place between a browser and the server. A similar effect has been achieved in non-standardized ways using stop-gap technologies such as Comet. [1] In addition, the communications are done over TCP port number 80, which is of benefit for those environments which block non-web Internet connections using afirewall. The WebSocket protocol is currently supported in most major browsers including Google Chrome, Internet Explorer, Firefox, Safari and Opera. WebSocket also requires web applications on the server to support it. How to test if your browser supports websockets: go to www.websocket.org/echo.html Using websockets in Tomcat http://www.tomcatexpert.com/blog/2012/05/01/how-apache-tomcat-implemented-websocket This is a link that describes new facilities in Tomcat to implement web sockets. Basically you extend WebSocketServlet class, which has the following methods: createWebSocketInbound WebSocket messages can come in binary form, onBinaryData, or text form, onTextData, and your application may choose to utilize one or both of these methods. Once you’ve created a class that implements both these methods your application is ready to receive messages. Your code that implements the createWebSocketInbound method would typically create a subclass of MessageInbound, which will live for as long as the connection is active. An example implementation would look like this (only text data) private final class ChatMessageInbound extends MessageInbound { @Override protected void onBinaryMessage(ByteBuffer message) throws IOException { //this application does not expect binary data throw new UnsupportedOperationException("Binary message not supported."); } @Override protected void onTextMessage(CharBuffer message) throws IOException { String msg = message.toString(); //modify the message by adding a timestamp msg = “(“ + System.currentTimeMillis()+”) “+ msg; broadcast(msg); } Page 1 private void broadcast(String message) { //write some code to process the message } } Writing data is pretty straightforward. Your StreamInbound implementation will have a reference to the sender component, WsOutbound. You simply retrieve it by calling myStreamInbound.getWsOutbound() at that point you can send either binary public void writeBinaryData(int b); public void writeBinaryMessage(ByteBuffer msgBb); or textual data to the client public void writeTextData(char c); public void writeTextMessage(CharBuffer msgBb); So why do we have two methods for sending textual and two methods for sending binary data? The answer is one of them is streaming, the other is to send a buffered message. When streaming messages, meaning you are using one of these two methods public void writeTextData(char c); public void writeBinaryData(int b); These methods are mutually exclusive. Don’t call both of these methods and expect both binary and textual data to be sent. When you’re done streaming, simply call public synchronized void flush() throws IOException; If you previously called writeTextData(char c) you can switch to binary data after calling flush(). Calling flush() completes the WebSocket message. A message can be sent down to the client in multiple frames (or fragments), a frame being a WebSocket defined set of data. When you use the public void writeTextMessage(CharBuffer msgBb); public void writeBinaryMessage(ByteBuffer msgBb); methods each set of data gets transferred as a message. In the Apache Tomcat WebSocket Chat example, each time a message is received, it broadcasts that message to the other clients as a separate message. private void broadcast(String message) { for (ChatMessageInbound connection : connections) { try { CharBuffer buffer = CharBuffer. wrap(message); connection.getWsOutbound().writeTextMessage(buffer); } catch (IOException ignore) // Ignore } } } Suggestions for content format Basically you should use JSON, and binary pack it. Page 2 WebSockets Questions What application server support is needed? Tomcat version 7.0.27 (released in 2012) is the first one to provide this. How does this compare to message transfer protocols such as TIBCO Rendezvous? It appears that the main difference is that you can’t carry out wildcard subscribing, efficient distribution to lots of clients, any higher quality of service, or any content-neutral wire formats (essentially JSON has taken the place in today’s industry that TIBCO Rendezvous Messages used to provide). Introduction to Atmosphere Real Time Client Server Framework for the JVM, supporting WebSockets and Cross-Browser Fallbacks Support It contains a server-side library (a Java jar file) for one side, and a client side library (a .js) file for the client. The result is that one doesn’t have to deal with lower-level HTTP details of using WebSockets. Resources Source code at https://github.com/Atmosphere Tutorial at http://async-io.org/tutorial.html Why Async-IO.org? Async-IO.org is the company behind the Atmosphere Framework! The Atmosphere Framework is the most popular asynchronous application development framework for enterprise Java. The Atmosphere Framework provides the enterprise features required to build massive scalable and real time asynchronous applications using transports like WebSocket, Server Side Events and traditional Ajax Techniques. It's been proven in production: Reverb, Wall Street Journal, GameDuell, VMWare, Atlassian and many more. Easy to write portable and asynchronous applications with a really simple API for both client and server Supports WebSockets and fallback transports transparently Proven to scale Cloud Enabled! Broadcaster The Broadcaster object is created to be the server side of a subscription. A Broadcaster is responsible for delivering messages to its subscribed AtmosphereResources, which are representing suspended responses. AtmosphereResource can be added usingaddAtmosphereResource(org.atmosphere.cpr.AtmosphereResource), so when broadcast(java.lang.Object) is executed,AtmosphereHandler.onStateChange(org.atmosphere.cpr.AtmosphereResourceEv ent) will be invoked and the suspended connection will have a chance to write the message available usingAtmosphereResourceEvent.getMessage(). A Broadcaster will by default use an ExecutorService, and the number of Threads will be computed based on the number of cores/CPUs of the OS under which the application runs. Thus invoking broadcast(Object) will be executed asynchronously so this is important to wait for the Future.get() to awake/unblock to be guaranteed that the operation has completed. One final word on Broadcaster: by default, a Broadcaster will broadcast using all AtmosphereResource on which the response has been suspended, e.g. {AtmosphereResource#suspend()} has been invoked. This behavior is configurable and you can configure it by invoking the setScope(org.atmosphere.cpr.Broadcaster.SCOPE) ): Page 3 REQUEST: broadcast events only to the AtmosphereResourceEvent associated with the current request. APPLICATION: broadcast events to all AtmosphereResourceEvent created for the current web application. VM: broadcast events to all AtmosphereResourceEvent created inside the current virtual machine. DefaultBroadcaster The default Broadcaster implementation. Broadcast messages to suspended responses using the caller's Thread. This basic Broadcaster use an ExecutorService to broadcast messages, hence the broadcast operation is asynchronous. Make sure you block on broadcast(Object).get()} if you need synchronous operations. Meteor A Meteor is a simple class that can be used from a Servlet to suspend, broadcast and resume responses. A Meteor can be created by invoking the build() method. Meteor.build(HttpServletRequest).suspend(-1); A Meteor is usually created when an application needs to suspend a response. A Meteor instance can then be cached and re-used later for either broadcasting a message, or when an application needs to resume the suspended response. AtmosphereResource https://github.com/Atmosphere/atmosphere/wiki/Understanding-AtmosphereResource Atmosphere Questions Is this Scala specific? No Page 4