Wednesday, September 18, 2013

Chatting with Web Sockets

Web Sockets enable direct socket connections between a web browser and a web server.
Newer versions of PAW support text based Web Sockets. This post shows how to build a small Web Sockets based chat server.

If you have ever tried coding a web based chat server you have surely noticed that the task is not as easy as it might seem at the first look. You have to deal with sessions and have to synchronize clients and so forth. That’s one of the reasons why I never did that ;).
We will see that with Web Sockets there are only a few lines of code necessary on the server side.

I will not go into much detail when it comes to the HTML part, this is standard and everybody can google that.
What I will explain in detail is the PAW setup and the server side BeanShell script included in implementing the chat server.

Configuring the Web Socket Handler

To enable Web Socket support for your PAW server, we have to insert and configure the Web Socket handler inside the handler.xml file. The file is located inside the conf folder of your PAW installation directory . The installation directory is normally /sdcard/paw. Inside the handler.xml file the installation directory is referenced as [PAW_HOME].

The handler can be places right in front of the configuration file inside the <handlers>...</handlers>

<handler status="active">
    <name>WebSocket Handler</name>
    <description>WebSocket Handler</description>
      <param name="websocket.class" value="" />
      <param name="websocket.basedir" value="[PAW_HOME]" />
      <param name="websocket.config" value="[PAW_HOME]/webconf/websocket.conf" />

There are two important parameters in that handler definition… basedir and config.

Let’s start with config. The parameter config specifies the location of the Web Socket definition file. This file defines rules that describe which BeanShell script (or Java class) to call if a Web Socket connection requesting a specific protocol comes along.

A Web Socket communication can specify a protocol to use, which makes it possible for the server to react differently even if listening to the same port.
A common protocol type is chat which the client sends to the server within the header when the connection is established. You can also define your own protocol, it’s just a text.

In our example the web browser will send a different protocol for each chat room which makes it possible for the server to distinguish them. So if a chat room is called talk, the protocol will be

The other parameter basedir defines the base directory of the BeanShell scripts which are defined inside the Web Socket configuration file.

In the next step, we’ll create the Web Socket config file.

Web Socket Config File

As defined in the handler definition, create a file called [PAW_HOME]/webconf/websocket.conf with the following content:

# Format:
# Protocol:Bsh script (.bsh extension) or class name

That’s it, actually quite simple. I’ll quickly explain the syntax.
The parameters are devided by colons.

First parameter is the protocol which is defined as a regular expression. So in our case the server will call the script html/websocket/websocket_chat.bsh for all protocols starting with chat. Now you already know the second parameter which is the BeanShell script to call.

Actually you can also use a Java class (or performance reasons) but this will not be handled inside this post. More about how to get this working with Java classes can be found inside the PAW Functions section of the PAW web interface.

The next step is to create the BeanShell script.

The BeanShell Script

Before creating the script, some infos in advance.
The handler sets some variables before it calls the script. These variables are action, message, sockets and socket.
The action variable tells us something about the state of the communication. Possible values are connect, disconnect  or text. The state important for us is text because it indicated that a text message has been sent by a client.

If text is set, there is also a variable called message which contains the message itself.

Let’s now have a look at the code, because I think will make things clearer.
Create a file called [PAW_HOME]/html/websocket/websocket_chat.bsh
 with the following content:


if(action.equals("text")) {
    for(sock : sockets) {
        try {
            WebSocketMessage.sendMessage(message, sock);
        catch(e) {

That’s the complete server side code. First thing that is checked is if the action variable is set to text which indicates that a message text is available inside the message variable.

If a message is present the code iterates over the sockets collection. The sockets collection contains all client socket connections that have the same protocol.
The socket collections are grouped by Web Socket protocol names, so we are sure that all sockets inside the collection belong to the same chat room.
As mentioned above, the web browser sends different Web Socket protocol names for each chat room (chat.>chatroom>).

So all that is left is to send the incoming message to all connected client. This is done by the following line:

 WebSocketMessage.sendMessage(message, sock);

The try/catch block is there to close a socket if something goes wrong.

One variable that is not present in the code and therefore was not handled until now is the socket variable. This variable contains the socket of the client that delivered the message.

The HTML File

The only thing that is missing is now the HTML file that is responsible for opening the Web Socket connection from the web browser. This is actually a XHTML file because it contains some additional BeanShell code.

The file can be downloaded from the link below. Just copy it into the [PAW_HOME]/html/websocket/ directory.
Now you can start your browser and call the XHTML file by inserting the following address into your browser’s address bar:


Web Socket Chat

If everything goes well, the Web Socket chat server should be up and running.
In case of questions, write a comment or send me a mail.

Happy coding :)



No comments:

Post a Comment

Note: Only a member of this blog may post a comment.