Home > Netzwerke, Programmierung, SW-Technik > Chess game via WebSockets

Chess game via WebSockets

November 9th, 2014

Here a small example what is possible with the HTML 5 WebSocket protocol, which is supported by almost all modern web browsers.

A WebSocket is a bidirectional connection between a browser and a server. It is possible to send and receive text messages from both directions in “nearly real-time”. With “nearly real-time” I mean that the human senses do not notice significant delays, when the network connection is fast and stable. WebSockets are suitable for web applications that have high interactivity and low data volumes, like e.g. a chat program or a computer game.


This example shows a chess program that runs on my server, using my buggy and incomplete chess engine I wrote a few years ago.

On the client side, there is a JavaScript program that sends the moves of the user to the server and receives moves of the computer. The client is very dumb and does not know the chess rules. The validation is done completely on the server.  With every message, the server sends the complete (new) position which is updated by the client on the chess board.

The message format is JSON, because this can easy be deserialized /serialized from/to JavaScript objects on the client side.

This application uses three types of messages:

  • Request: The Client sends a request to the server, like “I want to start an new game” and “I want to make a move.”
  • Response: As a reaction of a client request, the server sends back a response. I think it is reasonable for most applications to always send a response to the client, even if it is only a note that the message was received. Here the server sends something like “New game was started”, “your move was accepted”, “Your move was rejected” (invalid move, not your turn, …) and so on.
  • Event: An asynchronous message that is sent by the server if an event (on server side) occured. In this example: “the chess program made a move”.

The “Request/Response” mechanism is exactly what the traditional Client/Server model does and is easily possible with HTTP only. The advantage of WebSockets is that messages of type “event” are fairly simple to realize.

The second big advantage of a WebSocket connection is, that is has state, compared to the statefulness of HTTP. There are many smart solutions to work around the statelessnes of HTTP. But indeed, one should consider if it is not better to use a protocol that is stateful by design. In our example, the state of the session is the current position on the chess board. This is stored by the server, where it belongs (in my opinion). Now the client only needs to forward the user’s moves to the server and display the current position.
On a stateless server, the client would have to ask every time “compute a move for this position” and the client would keep track of the position. This would be possible, but feels unnatural to me.
On the other side, the advantage of a stateless web server is the high scalability. You could replace or add a new server anytime.

The WebSocket client uses require.js, jQuery, the great chessboard.js library and – of course – websockets to run. With that, the client code shrinks to a few lines:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
define(['jquery', 'chessboard'], function() {
    var url = "ws://" + location.hostname + ":" + location.port + location.pathname + "endpoint";
    var ws = new WebSocket(url);
    var cfg = {
        draggable: true,
        position: 'start',
        onDrop: function(source, target, piece, newPos, oldPos, orientation) {
            if (source === target) {
                return;
            }
            ws.send(JSON.stringify({
                message: 'set move',
                type: 'request',
                from: source,
                to: target}));
        }
    };
    var board = new ChessBoard('board', cfg);
    board.start();
 
 
    ws.onopen = function()
    {
        ws.send(JSON.stringify(
                {message: 'new game',
                    type: 'request'}));
    };
    ws.onmessage = function(evt)
    {
        var message = JSON.parse(evt.data);
        if (message.message === 'new game' && message.type === 'response') {
            board.position(message.position);
        } else if (message.message === 'set move' || message.message === 'new move') {
            board.position(message.position);
        }
    };
    ws.onclose = function()
    {
        console.log("Connection is closed...");
    };
});
Comments are closed.