Any technology around HTML5 seems to be a hot button topic these days and lucky for me that I got an opportunity to take a deep dive into WebSockets. Be it canvas, geolocation, video playback, drag-and-drop or WebSocket , there is a lot of buzz around these upcoming technologies.
Some background on HTML5 WebSockets
HTML5 WebSocket defines a bi-directional, full-duplex communication channel operates through a single TCP connection. The important thing to note is the WebSocket API is being standardized by the W3C, and the WebSocket protocol has been standardized by the IETF as RFC 6455.
What this means is that there are bunch of protocol versions and today's browsers support specific protocols versions only. e.g. Chrome 14, Firefox 7 and Internet Explorer 10 are currently the only browsers supporting the latest draft specification ("hybi-10") of the WebSocket protocol. The same goes for web servers. Different web servers are in varying stages of support for asynchronous messaging, with Jetty, Netty and Glassfish being the best options currently a provide native WebSocket support.
Tomcat 7 currently does not support WebSockets, yet. Check out the following issue tracker entry to learn more about the current state of affairs in Tomcat 7:
https://issues.apache.org/bugzilla/show_bug.cgi?id=51181
Socket.IO provides a default implementation for Node.JS.
It is expected that HTML5 WebSockets will replace the existing XHR approaches as well as Comet services by a new flexible and ultra high speed bidirectional TCP socket communication technology.
Technical details about WebSocket
In short: Web Sockets can make your applications faster, more efficient, and more scalable.
The WebSocket Interface:
A typical Javascript client:
Getting started with WebSockets with Java backend
To build applications around websockets, I will focus on Jetty, Netty and Atmosphere for building websocket applications. The focus will be on backend processing. JQuery or raw Javascript can be used as client. We will work with a sample chat application.
1. Jetty 8
Jetty is a Java-based HTTP server and servlet container. Jetty 8 is Servlet 3.0 container and provides WebSocket implementation, so that it is possible to offer server push via both HTTP and WebSocket protocol. Jetty provides WebSocket implementation as a subclass of HttpServlet. Here is a Jetty server example:
The advantage of this approach is that it means that WebSocket connections are terminated in the same rich application space provided by HTTP servers, thus a WebSocket enabled web application can be developed in a single environment rather than by collaboration between a HTTP server and a separate WebSocket server.
2. Atmosphere
Atmosphere is a WebSocket/Comet web framework that enables real time web application in Java. Atmosphere really simplifies a real time web application development and works with servlet containers that do not implement Servlet 3.0 but natively support Comet such as Tomcat 6. Here is an exmaple:
Conclusion
There are many resources on www describing websockets; and many libraries trying to solve the application portability problem. To a developer trying to embrace the upcoming websockets technology, it can be confusing and overwhelming.
For others who want to integrate websockets into an existing application, there is dilemma about choosing the framework and technology stack. Building applications around HTML 5 websockets is going to be tricky for next few months till the API and protocols are standardized and the open source community provides native implementations. Using Atmosphere and jWebSockets makes sense as it abstracts out the underlying provider.
I will be writing more about Atmosphere and jWebSocket in my future blog posts.
Further reading:
http://www.html5rocks.com/en/tutorials/websockets/basics/
http://websocket.org/
http://en.wikipedia.org/wiki/WebSockets
Part 2:
Some background on HTML5 WebSockets
HTML5 WebSocket defines a bi-directional, full-duplex communication channel operates through a single TCP connection. The important thing to note is the WebSocket API is being standardized by the W3C, and the WebSocket protocol has been standardized by the IETF as RFC 6455.
What this means is that there are bunch of protocol versions and today's browsers support specific protocols versions only. e.g. Chrome 14, Firefox 7 and Internet Explorer 10 are currently the only browsers supporting the latest draft specification ("hybi-10") of the WebSocket protocol. The same goes for web servers. Different web servers are in varying stages of support for asynchronous messaging, with Jetty, Netty and Glassfish being the best options currently a provide native WebSocket support.
Tomcat 7 currently does not support WebSockets, yet. Check out the following issue tracker entry to learn more about the current state of affairs in Tomcat 7:
https://issues.apache.org/bugzilla/show_bug.cgi?id=51181
Socket.IO provides a default implementation for Node.JS.
It is expected that HTML5 WebSockets will replace the existing XHR approaches as well as Comet services by a new flexible and ultra high speed bidirectional TCP socket communication technology.
Technical details about WebSocket
- Uses WebSocket protocol instead of HTTP
- True full duplex communication channel; UTF8 strings and binary data can be sent in any direction at the same time.
- It is not a raw TCP socket
- Connection established by "upgrading" (handshake) from HTTP to WebSocket protocol
- Runs via port 80/443 and is firewall/proxy friendly
- Supports WebSocket ws:// and secure WebSocket wss://
- Reduces network traffic. each message has 2 bytes of overhead
- Low latency
- No polling overhead
In short: Web Sockets can make your applications faster, more efficient, and more scalable.
The WebSocket Interface:
interface WebSocket {
....
//ready state
const unsigned short CONNECTING = 0;
const unsigned short OPEN = 0;
const unsigned short CLOSING = 0;
const unsigned short CLOSED = 0;
..
//Networking
attribute Function onopen;
attribute Function onmessage;
attribute Function onerror;
attribute Function onclose;
boolean send(in data);
void close();
};
A typical Javascript client:
var wsUri = "ws://echo.websocket.org/";
function init()
{
testWebSocket();
}
function testWebSocket()
{
websocket = new WebSocket(wsUri);
websocket.onopen = function(evt) { onOpen(evt) };
websocket.onclose = function(evt) { onClose(evt) };
websocket.onmessage = function(evt) { onMessage(evt) };
websocket.onerror = function(evt) { onError(evt) };
}
function onOpen(evt)
{
writeToScreen("CONNECTED");
doSend("WebSocket rocks");
}
function onClose(evt)
{
writeToScreen("DISCONNECTED");
}
function onMessage(evt)
{
writeToScreen('RESPONSE: ' + evt.data+'');
websocket.close();
}
function onError(evt)
{
writeToScreen('ERROR: ' + evt.data);
}
function doSend(message)
{
writeToScreen("SENT: " + message);
websocket.send(message);
}
function writeToScreen(message)
{
var pre = document.createElement("p");
pre.innerHTML = message;
....
}
Getting started with WebSockets with Java backend
Jetty is a Java-based HTTP server and servlet container. Jetty 8 is Servlet 3.0 container and provides WebSocket implementation, so that it is possible to offer server push via both HTTP and WebSocket protocol. Jetty provides WebSocket implementation as a subclass of HttpServlet. Here is a Jetty server example:
@WebServlet(urlPatterns = "/chat", asyncSupported = true)
public class ChatServlet extends WebSocketServlet {
// GET method is used to establish a stream connection
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//Implementation
}
// POST method is used to communicate with the server
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//Implementation
}
@Override
public WebSocket doWebSocketConnect(HttpServletRequest request, String protocol) {
return new ChatWebSocket();
}
private Queue webSockets = new ConcurrentLinkedQueue();
class ChatWebSocket implements WebSocket.OnTextMessage {
Connection connection;
@Override
public void onOpen(Connection connection) {
this.connection = connection;
webSockets.add(this);
}
@Override
public void onClose(int closeCode, String message) {
webSockets.remove(this);
}
@Override
public void onMessage(String queryString) {
// Parses query string
UrlEncoded parameters = new UrlEncoded(queryString);
Map data = new LinkedHashMap();
data.put("username", parameters.getString("username"));
data.put("message", parameters.getString("message"));
try {
messages.put(new Gson().toJson(data));
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
@Override
public void onClose(int closeCode, String message) {
webSockets.remove(this);
}
}
}
The advantage of this approach is that it means that WebSocket connections are terminated in the same rich application space provided by HTTP servers, thus a WebSocket enabled web application can be developed in a single environment rather than by collaboration between a HTTP server and a separate WebSocket server.
2. Atmosphere
Atmosphere is a WebSocket/Comet web framework that enables real time web application in Java. Atmosphere really simplifies a real time web application development and works with servlet containers that do not implement Servlet 3.0 but natively support Comet such as Tomcat 6. Here is an exmaple:
public class ChatAtmosphereHandler implements
AtmosphereHandler {
public void onRequest(AtmosphereResource resource)
throws IOException {
HttpServletRequest request = resource.getRequest();
HttpServletResponse response = resource.getResponse();
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
// GET method is used to establish a stream connection
if ("GET".equals(request.getMethod())) {
// Content-Type header
response.setContentType("text/plain");
resource.suspend();
// POST method is used to communicate with the server
} else if ("POST".equals(request.getMethod())) {
Map data = new LinkedHashMap();
data.put("username", request.getParameter("username"));
data.put("message", request.getParameter("message"));
// Broadcasts a message
resource.getBroadcaster().broadcast(new Gson().toJson(data));
}
}
public void onStateChange(AtmosphereResourceEvent event)
throws IOException {
if (event.getMessage() == null) {
return;
}
sendMessage(event.getResource().getResponse().getWriter(), event.getMessage().toString());
}
private void sendMessage(PrintWriter writer, String message) throws IOException {
// default message format is message-size ; message-data ;
writer.print(message.length());
writer.print(";");
writer.print(message);
writer.print(";");
writer.flush();
}
}
Conclusion
There are many resources on www describing websockets; and many libraries trying to solve the application portability problem. To a developer trying to embrace the upcoming websockets technology, it can be confusing and overwhelming.
For others who want to integrate websockets into an existing application, there is dilemma about choosing the framework and technology stack. Building applications around HTML 5 websockets is going to be tricky for next few months till the API and protocols are standardized and the open source community provides native implementations. Using Atmosphere and jWebSockets makes sense as it abstracts out the underlying provider.
I will be writing more about Atmosphere and jWebSocket in my future blog posts.
Further reading:
http://www.html5rocks.com/en/tutorials/websockets/basics/
http://websocket.org/
http://en.wikipedia.org/wiki/WebSockets
Part 2:
No comments:
Post a Comment