Web Sockets

Today we look into Websockets and provide two small code examples.

What are Websockets?

In short summary you can paraphrase the key notions of WebSockets like this:

  • WebSockets is a technique for two-way communication over one TCP socket.
  • It is designed to be implemented in web browsers and web servers.
  • It is an extra part of the coming HTML5 standard.
  • It is a generalized kind of AJAX, including a PUSH technology for the web.
  • It reduces unnecessary network traffic and latency compared to polling requests.

Websockets consists of two major parts:

The WebSockets Protocol

To establish a WebSocket connection, the client sends a WebSocket handshake request, and the server sends a WebSocket handshake response.
The handshake is done via the HTTP upgrade mechanism to upgrade to the WebSocket protocol.

Client request:

	GET /ws HTTP/1.1
	…
	Upgrade: websocket

Server response:

	HTTP/1.1 101 Switching Protocols
	Upgrade: websocket
	Connection: Upgrade
	Sec-WebSocket-Accept: …

By using standard HTTP for the handshake, the websockets traverse firewalls and proxies.
What is special about the websockets protocol is that it allows the client to connect to arbitrary endpoints and is not bound to „same location as original request“ policy.
The protocol and endpoint are notated with ws://hostname:port/uri or wss://hostname:port/uri for the encrypted version of the protocol.

Another remarkable fact is that there is no header data in protocol,. The payload is delimited with 1 start and 1 end byte,
so that the protocol overhead is exactly 2 bytes per message.
Standard HTTP request usually have something between 500 to 1000 bytes in header data.

The Websocket API

The Websocket API is a really small Javascript API, which allows the client to send and receice data over the websocket protocol.
The complete API can be listed within a single interface, which consists in a constructor, 4 event handlers and 2 methods.

	[Constructor(in DOMString url, optional in DOMString protocol)]
	interface WebSocket {
		readonly attribute DOMString URL;
		const unsigned short CONNECTING = 0;
		const unsigned short OPEN = 1;
		const unsigned short CLOSED = 2;

		readonly attribute unsigned short readyState;
		readonly attribute unsigned long bufferedAmount;       

		attribute Function onopen;
		attribute Function onmessage;
		attribute Function onclose;
		attribute Function onerror;

		boolean send(in DOMString data);
		void close();
	}

And here is how you use the API:

  1. Start handshake:
    		var myWebSocket = new WebSocket("ws://www.websockets.org");
  2. Define event handlers:
    		myWebSocket.onopen=function(evt) {
                      alert("Connection open ..."); };
    		myWebSocket.onmessage=function(evt) {
                      alert( "Received Message: "  +  evt.data); };
    		myWebSocket.onclose=function(evt) {
                      alert("Connection closed."); };
  3. Call the methods:
    		myWebSocket.send("Hello Web Sockets!");
    		myWebSocket.close();

What you need is a web browser which implements the Websocket API.
Since the standard is not yet finished, the implementations are ongoing process.
Currently Google Chrome 9, Apple Safari 5 and iOs Safari 4.2 implement it.
Firefox 4, Opera 11 and Opera Mobile 11 have also implemented it, bit disabled it by default.
And the IE 9 needs a extra plugin to support Websockets.

On the server side their are various implementation for the websocket protocol.
For Java you can use Glassfish 3.1, Jetty 7, Resin 4.0.2, jWebsocket.
All have their own APIs, since the websocket protocol is currently not part of Servlet Specification, but this may be added in JEE7.
For PHP there is phpwebsockets, for Python mod_pywebsocket, for Ruby web-socket-ruby and if you are doing
server-side JavaScript there is a plugin for node.js.

Example code: Hello Websockets

After all the explanation I want to go into two small examples. Let’s start with the “Hello World” of WebSockets.
We will do a Echo-Server, where the client will send some message over the wire and the server will send back the message.
For the server side I’ve chosen to use Jetty (since I’m a Java guy most of the time), and using Maven for the infrastructure.
So let’s have a look at the POM definition, after we created the project with the usual
archetype for a web application:

<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
    http://maven.apache.org/xsd/maven-4.0.0.xsd">
  ... // the usual stuff
  <packaging>war</packaging>
  <properties>
    <jetty.version>7.3.0.v20110203</jetty.version>
  </properties>
  <build>
    <plugins>
	...
      <plugin>
        <groupId>org.mortbay.jetty</groupId>
        <artifactId>jetty-maven-plugin</artifactId>
        <version>${jetty.version}</version>
        <configuration>
          <scanIntervalSeconds>10</scanIntervalSeconds>
          <webAppConfig>
            <contextPath>/websockets</contextPath>
            <descriptor>${basedir}/src/main/webapp/web.xml</descriptor>
          </webAppConfig>
        </configuration>
      </plugin>
    </plugins>
  </build>
  <dependencies>
    <dependency>
      <groupId>org.eclipse.jetty</groupId>
      <artifactId>jetty-server</artifactId>
      <version>${jetty.version}</version>
    </dependency>
    <dependency>
      <groupId>org.eclipse.jetty</groupId>
      <artifactId>jetty-websocket</artifactId>
      <version>${jetty.version}</version>
    </dependency>
  </dependencies>
</project>

If you look at it you’ll see that we’re using the Jetty Server as compile time dependency (for the Websocket API) and the runtime container.
That is the only thing we actually need, and so we can start coding the server side.
For the Jetty implementation of Websockets that means we have to implement a servlet, which inherits from the
org.eclipse.jetty.websocket.WebSocketServlet.

	package echo;

	import java.io.IOException;
	import javax.servlet.http.HttpServletRequest;
	import org.eclipse.jetty.websocket.WebSocket;
	import org.eclipse.jetty.websocket.WebSocketServlet;

	public class EchoServlet extends WebSocketServlet {

	  protected WebSocket doWebSocketConnect(HttpServletRequest req,
             String resp) {
		return new EchoWebSocket();
	  }

	  private class EchoWebSocket implements WebSocket {
		private Outbound outbound;

		public void onConnect(Outbound outbound) {
		  this.outbound = outbound;
		}

		public void onDisconnect() {
		  this.outbound = null;
		}

		public void onMessage(final byte frame, String data) {
		  try {
			System.out.println("Received: " + data);
			outbound.sendMessage("You said: " + data);
		  } catch (IOException e) {
			e.printStackTrace();
		  }
		}

		public void onMessage(byte arg0, byte[] arg1, int arg2, 
                  int arg3) {
		}

		public void onFragment(boolean arg0, byte arg1, byte[] arg2, 
                  int arg3, int arg4) {
		}
	  }
	}
	

 

What the servlet does is easy to see. When the handshake starts the doWebSocketConnect is called and we create our own Websocket.
This is the EchoWebSocket which has to implement the org.eclipse.jetty.websocket.WebSocket interface.
When the connection is established an Outbound is created, since we want to send the incoming message back to client.
And when a message arrives, the onMessage method is called, and we send the message back over the Outbound.
The other two message methods can have an empty implementation since we don’t intend to send binary data.
For the server to be complete we just have to register the Servlet in the web.xml.

What we need now is the client side. For that we code a JSP page, which delivers a small HTML page:

<!DOCTYPE html>
<html>
<head>
<title>My first WebSocket app!</title>
<script type="text/javascript">
	var ws = new WebSocket("ws://localhost:8080/websockets/echo");
	ws.onopen = function(ev) {
		window.alert("connection is up");
	};
	ws.onmessage = function(ev) {
		document.getElementById("receive").innerHTML = ev.data;
	};
	function send() {
		ws.send(document.getElementById("send").value);
	}
</script>
</head>
<body>
  <h2>Websocket Hello World</h2>
  <input type="text" id="send" size="40" /> 
  <input type="button" value="send" onclick="send()"/>
  <hr/>
  <p id="receive"/>
</body>
</html>
	

 

There’s not much magic in there either. The page has a text input for the message to be sent and a paragraph section for the answer that we receive.
When the page is loaded the WebSocket is created.
When you click on the button the input message is send, and when a message comes in, the payload is put into the paragraph.

Now we got all pieces together, and with mvn jetty:run we can start the servlet engine and point our browser
to http://localhost:8080/websockets/echo.jsp.

What to do with Websockets?

There are really huge fields to which you can apply websockets.
Think about all applications which have “real-time” communication patterns like chat server, twitter clients, collaboration, messaging, push email, news ticker or stock brokers

And you are not limited to raw data or simple string being send over the wire.
The next level yould be to send formatted data (as in XML or JSON), but you can also implement
high-level protocols messaging protocols on the client side (like JMS, Jabber or AMQP).
And since you are no longer bound to the same origin policy as in AJAX requests, you can
replace and out-scale traditional AJAX requests: lower latencies by pushing data,
save resources on the server side by avoiding long polling requests and a lower protocol overhead.

A more complex example: pushing server monitoring data

Now let’s get to a more complex example. We want to push server monitoring data (like the memory our VM uses) to a listening client.
Sampling monitoring data can be done with JMX, using the java.lang.management.ManagementFactory..
Calling ManagementFactory.getMemoryMXBean() delivers the java.lang.management.MemoryMXBean,
which we can ask about the status of the VM’s memory:


		MemoryMXBean.getHeapMemoryUsage().getInit());
		MemoryMXBean.getHeapMemoryUsage().getCommitted());
		MemoryMXBean.getHeapMemoryUsage().getUsed());
		MemoryMXBean.getHeapMemoryUsage().getMax());
		MemoryMXBean.getNonHeapMemoryUsage().getInit());
		MemoryMXBean.getNonHeapMemoryUsage().getCommitted());
		MemoryMXBean.getNonHeapMemoryUsage().getUsed());
		MemoryMXBean.getNonHeapMemoryUsage().getMax());
		MemoryMXBean.getObjectPendingFinalizationCount());
	

 

So what we do is quite straight forward. We create a plain Java Bean MemoryUsage which can hold all this data, and we create a timer task
which reads the data from the MemoryMXBean on a regular basis and creates a MemoryUsage object.


	public class MemoryUsage {
		private long heapMemoryUsageInit;
		private long heapMemoryUsageUsed;
		private long heapMemoryUsageCommitted;
		private long heapMemoryUsageMax;
		private long nonHeapMemoryUsageInit;
		private long nonHeapMemoryUsageUsed;
		private long nonHeapMemoryUsageCommitted;
		private long nonHeapMemoryUsageMax;
		private int objectPendingFinalizationCount;
		private long timestamp;

		// add getters and setters
	}

	public class MonitoringSocket implements WebSocket {
		// similar to the echo websocket

		private java.util.Timer timer;

		public void onConnect(Outbound outbound) {
			this.outbound = outbound;
			timer = new Timer();
			timer.schedule(new java.util.TimerTask() {
				public void run() {
					outbound.sendMessage(frame, 
                                                 stringify(getData()));
				}, new java.util.Date(), 2000);
			}
		}

		public void onDisconnect() {
			timer.cancel();
		}
	}
	

 

We create a websocket servlet and a WebSocket instance like we did in the Echo example.
What we add is a TimerTask we start when a connection is created.
This task is tunning every 2 seconds and will get the monitoring data and make a text message out of the
MemoryUsage object. What is now still missing are the getData() and the stringify()
methods. The first one is a simple one, just create the Java Bean and set its values from JMX:


  public MemoryUsage getData() {
    MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
    MemoryUsage memoryUsage = new MemoryUsage();
    memoryUsage.setHeapMemoryUsageInit(
      memoryMXBean.getHeapMemoryUsage().getInit());
    memoryUsage.setHeapMemoryUsageCommitted(
      memoryMXBean.getHeapMemoryUsage().getCommitted());
    memoryUsage.setHeapMemoryUsageUsed(
      memoryMXBean.getHeapMemoryUsage().getUsed());
    memoryUsage.setHeapMemoryUsageMax(
      memoryMXBean.getHeapMemoryUsage().getMax());
    memoryUsage.setNonHeapMemoryUsageInit(
      memoryMXBean.getNonHeapMemoryUsage().getInit());
    memoryUsage.setNonHeapMemoryUsageCommitted(
      memoryMXBean.getNonHeapMemoryUsage().getCommitted());
    memoryUsage.setNonHeapMemoryUsageUsed(
      memoryMXBean.getNonHeapMemoryUsage().getUsed());
    memoryUsage.setNonHeapMemoryUsageMax(
      memoryMXBean.getNonHeapMemoryUsage().getMax());
    memoryUsage.setObjectPendingFinalizationCount(
      memoryMXBean.getObjectPendingFinalizationCount());
    memoryUsage.setTimestamp(System.currentTimeMillis());
    return memoryUsage;
}

And how you want to deliver the data to the client is left as an execise to the reader, there may be different ways you might want to go:

  • Make a larger text string where you format the name and the value. The client can paste the message in a text box as we did in the echo example.
  • Write a method which makes a HTML snippet out of the values, or format the data to XML
  • Use a bean serialization engine and deliver XML or JSON to the client. In my code I have used
    the Jackson JSON Processor.

On the client side we use the approach as before, using JSP to deliver HTML pages and JavaScript.
Since I have decided to deliver JSON arrays to the client, the message handler in JavaScript takes the
JSON data and puts them into HTML table cells. This is pretty straight-forward code, so if you want to have look at it
take a look at the sources.

From here on…

Download the source code – with some more gimmicks – from the examples I’ve shown.

If you want dig deeper into the matter you can visit http://websocket.org for more
information, or go to the standards body and have a look at the
WebSocket API and
the WebSocket protocol definitions.

Tagged : , , , ,

One Response to “Web Sockets”

  1. hi i am new to web socket world.so can you send me the source code for above example(Hello Websockets)?

Leave a Reply