in Code

Building Real-time Chess with Socket.io

Tony Fischer Chess in Washington Square Park (Flickr)
Tony Fischer Chess in Washington Square Park (Flickr)

Chess is sweet. If you’ve ever been to Washington Square Park in New York City and watched a few games in action, or been to any of the chess halls, you know the energy of the game. Chess can be thrilling. It may start slow as the board establishes itself, but as the game approaches its critical moves the impact of each painful move is apparent in the audible groans of the player nearing his demise.

Slow chess is lame

I’ve been playing a lot of Chess with Friends on the iPhone. It’s a good multiplayer chess game, but the one thing that really bugs me is how slow each move can take to reach your opponent over the internet. I’ll make an awesome Queen busting setup move against my brother in law, and even if I know he’s staring at the game, it may be seconds or even minutes before he sees my move, and much longer till I get his futile response.

Mission: Real-time multiplayer chess

So, let’s make a multiplayer chess game that where when you make a move it’s reflected on your opponent’s screen in real-time. Instantly. Checkmate.

I’m no expert at making online chess games or even any multiplayer games at all, but I have played with making some tutorials for making real-time chat apps. So for this, we’re going to build on the shoulders of giants and pull in some of the great work of the open source community.

That’s what I love about open source — it takes something that may be out of reach for you, and makes it like putting Legos together.

The steps

Step 1: Make a basic chess game

Building a chess game is no easy task on it’s own, but there are some sweet client-side JavaScript chess libraries we’re going to pull in to make it easy.

What we need

  • Chessboard.js – This is a full interactive touch ready chessboard that let’s you programmatically place chess pieces, respond to player movements through event callbacks, and customize piece theme. This is the UI and visual behavior.
  • Chess.js – This is the chess logic. It will know if something is a valid chess move and maintain the game logic and state. What’s cool is that it’s compatible with Chessboard.js by using a standard FEN notation for board layout and game moves.

Chess markup (public/default.html)

<body>
    <div id="gameBoard"></div>
    <script src="../lib/chess.min.js"></script>
    <script src="../lib/chessboard-0.3.0.min.js"></script>
</body>

Chess game (public/default.js)

var initGame = function () {
    var cfg = {
        draggable: true,
        position: 'start',
        onDrop: handleMove,
    };

    board = new ChessBoard('gameBoard', cfg);
    game = new Chess();
}

var handleMove = function(source, target) {
    var move = game.move({from: source, to: target});
}

Step 2: The game server

Now we need a server that can serve up our client-side JavaScript chess game as well has run the code that responds to the game moves between all the players.

nodejs logo

What we need

  • Node.js – The only real dev language. Server-side JavaScript framework ideal for async operations.
  • Express – A server-side framework that simplifies hosting static and dynamic web content
  • Visual Studio Code – I use Visual Studio Code as my lightweight text editor because it’s fast and has an integrated Node.js debugger.

Serve up the HTML with Express (app.js)

var express = require('express');
var app = express();
app.use(express.static('public'));
var http = require('http').Server(app);
var port = 3000;

http.listen(port, function() {
    console.log('listening on *: ' + port);
});

So let’s check in and see what we’ve built. Let’s pop it open in our browser by running ‘node app.js’ in our developer console and opening http://localhost:3000 in our browser.

Picture of node console

We’ve got a simple chess game, where one player can make a move. There’s no opponent (player computer or otherwise) yet…let’s go add that.

Picture of node console

Step 3: Real-time with WebSockets

What’s going to make our chess game special is that it’s real-time and super fast to make, and respond to chess moves. WebSockets and the Socket.io JavaScript framework are the special sauce that is going to make this work.

Traditional TCP versus WebSockets

The traditional web talks through TCP (Transmission Connectivity Protocol). This works great for most scenarios where you’re loading a document of content, or logging into a portal.

How TCP works

  • Open connection to server
  • Describe payload in header
  • Send data
  • Close connection

While there are benefits to opening and closing the connection each time: e.g. stability and reliability of connection, less network, and battery usage. But there are downsides for something you want to be fast. There is significant overhead each time you open a new connection to the server. It may take a second or two on it’s own, and there could be latency anywhere in your connection — from your wifi router to your inernet provider to the server. You feel that delay with each connection, which really adds up if you’re playing at 100 move chess game.

WebSockets to the rescue!

WebSockets work differently than traditional TCP by keeping the connection open once it’s created. This may use more battery by keeping your wifi radio in action, but it does reduce latency for things you do wih that connection.

How WebSockets work

  • Open connection to server
  • Send/receive data all day
  • Close connection when you’re done

Since you’re keeping that same connection open all day, you remove the latency of creating it every time. This allows for near real-time interacivity for the stuff you’re building. It’s super cool.

Socket.io is real-time JavaScript unicorn tears

If all of WebSockets, and protocol mumbojumbo seems out of reach, don’t worry. Socket.io is an amazing client and server-side JavaScript framework that makes all the hard parts of traditional WebSocket communcation as simple as handling a JS callback. So good.

socketio logo

Let’s look at a little example of what it looks like to connect to a Socket.io server from a client and send a message.

What we need

  • Socket.io – Handy JS framework for doing real-time stuff with WebSockets.

Client (default.js)

// setup my socket client
var socket = io();
msgButton.onclick = function(e) {
    // someone clicked send a message
    socket.emit('message', 'hello world!');
}

Server (app.js)

// setup my socket server
var io = require('socket.io')(http);

io.on('connection', function(socket) {
    console.log('New connection');

    socket.on('message', function(msg) {
        console.log('Got message from client: ' + msg);
    }
}

Picture of node console

Sweet! So every time we push the button it logs the message, cool. If you’re following along and built this, you’ll recognize how fast this is shows up in the log. We’re on our way to fast chess.

Step 4: Connect game to the Socket.io server

Now that we have our chess game working, and a simple Socket.io server we can finally connect the dots and get the whole multiplayer part working.

Send move to your opponent

In our basic Socket.io server above, we just sent a message to the client every time someone clicked the button in their browser. For the chess game, all we need to do is send the chess move data to the Socket.io server every time there’s a move and send it to the other player. We’re going to use the same socket.emit() function to send a message, and the socket.on() handlers to respond to them.

Client (default.js)

// called when a player makes a move on the board UI
var handleMove = function(source, target) {
    var move = game.move({from: source, to: target});
    socket.emit('move', move);
}

For the server, we replace our sample “message” event handler with a “move” handler that is called by the client above. This move handler will broadcast the message to all the clients listening for messages.

Server (app.js)

// Called when the client calls socket.emit('move')
socket.on('move', function(msg) {
    socket.broadcast.emit('move', msg);
});

Handle and respond to moves from the server

Now that the server is broadcasting the move to the opponent all we need to do is handle that on the client to actually display the move. We just do that with another socket.on() calback, this time on the client. I think it’s super cool that Socket.io has the same programming model whether you’re on the client or server.

Client (default.js)

// called when the server calls socket.broadcast('move')
socket.on('move', function (msg) {
    game.move(msg);
    board.position(game.fen()); // fen is the board layout
});

Cool! Now we’ve got the multiplayer chess working. Awesome. we can test it by running ‘node app.js’ in our developer console and opening http://localhost:3000 in our browser. Open up two tabs and you’ll see the board on one tab respond after the other one makes a move. No delays, instant. Yus.

Step 5: Publish it to Azure

It’s great we’ve got our game working on our local Express server but that’s not enough for me. I need to put it out there so I can start playing faster chess with my family. To do this, we need to publish it on the internets. It’s a Node app so there are a number of places I could publish it like a Heroku app or an AWS EC2 instance. I’m going to use Azure, since I like how it let’s me deploy from GitHub.

What we need

  • Microsoft Azure account – You can get a free account with a bunch of free hosting credits to spend, or if you’re a Student or Startup you can get plenty of free hosting to go live.
  • GitHub account – GitHub is a free source control and versioning system that’s awesome and you should be using it.

Create an Azure Web App

In our Azure portal we’re going to new up a web app that we can publish our code to. It’s pretty easy, we just click the ‘Quick Create’ web app option.

Screenshot of azure configure tab with WebSockets

What’s cool is we don’t need to tell it what type of server we’re running (e.g. Node vs. Java vs. ASP.NET) because Azure will take a look at our code and make the determiniation automatically.

Enable WebSockets

As we discussed earlier, Socket.io takes advantage of WebSockets for the messages it sends around. These are not enabled on my server by default to reduce the security and attack vector. It’s easy to enable them from the ‘Configure’ tab.

Screenshot of azure configure tab with WebSockets

Deploy to Azure from GitHub

I’m going to assume we’ve committed and pushed our code to our GitHub repo and we’re ready to to publish it to Azure. If you want to learn more about committing to GitHub check out this GitHub tutorial.

We can just choose ‘Deploy from Source Control’ and choose GitHub, and the repo that we want to deploy to.

GitHub deploy

Immediately we’ll see the code start to deploy to Azure from our GitHub. This is toally set up for automatic continuous deployment, so every time I make a commit it will push it to the Azure web server. Awesome.

GitHub Deploy animation

All together now

So we did a ton of cool stuff to build our simple multiplayer chess game and play it online. Let’s recap on what we had to build to get it going.

Quick recap

  1. We built a simple JavaScript chess game with Chess.js and Chessboard.js
  2. We built a simple Node.js and Express server that hosts the chess game JavaScript
  3. We added Socket.io to our Node server to send and handle messages from the clients, first with a simple buton
  4. We sent Socket.io messages to the server when the player completes her move, and broadcast it to the clients from the server.
  5. We published the whole game online so we can start crushing our in-laws in real-time.

Try it out!

Go ahead and try it all in action here:
http://realchess.azurewebsites.net

Ideas for what’s next

  • Use REDIS Cache for variables so the server can auto-scale beyond one instance
  • NOSQL backend to store games and players
  • Facebook authentication
  • Wrap the UI in a better framework like Ionic
  • Ship on mobile platforms using Cordova
  • Mobile push notifications
  • Consider building a 3D interface in Unity
  • Add some hardware component, because hardware

Get the code

Human knowledge belongs to the world. Fork it, tweak it, play with it and build the next multiplayer chess empire!

A test server for web sockets project
https://github.com/dwcares/realchess
16 forks.
0 open issues.
Recent commits:

Building a delicious “hamburger” button app layout

In the previous post, Designing a delicious “hamburger” button app layout, we walked through, why apps use the hamburger layout style and some design elements that make up a good implementation. In this post, we’ll walk through how to build a great implementation in HTML and JavaScript, targeting Windows Phone and Windows 8. We’ll work to build […]