Tuesday, July 30, 2013

Real Time Communication with Socket.io

Socket.io lets us enable real-time communication between web browsers. In this basic tutorial I'll show you how to build a simple "game" that lets you pass a puck back and forth between clients in real time.

The basic steps will be:
  1. Install Node.js.
  2. Install Socket.IO.
  3. Create a directory for your project containing the backend code (title it app.js) and a file for the frontend (title it index.html).
  4. From the command line and inside the project directory start the server by typing: node app.js 
  5. Open a browser and point it at: http://localhost:4000.
  6. Open a second browser and point it at the same URL.
  7. Click the puck and watch socket.io work its magic!
Let's get started!


You will need Node.js installed as a first step so go install that if you haven't already. Once you have that in place you will need to install Socket.io. Assuming Node.js is installed correctly all you need to do use npm (Node Package Manager) like so:

sudo npm install socket.io


I'll present the full backend code and then go through explaining what everything does.

In the first 5 lines of the backend we define variables and tell the server which port we will be on: Lines 1-3 define and create the server (app), socketio (io) and the filesystem (fs). The first two are fairly self-explanatory. The third, filesystem, is needed because we have to read in the index.html file that will contain our frontend code.

Line 5 tells the server to operate on port 4000. The port doesn't really matter for this tutorial (any open port will do) but be aware that you cannot run your app as a non-privileged user on ports lower than 1024. Attempts to do so will result in the following error:

warn - error raised: Error: listen EACCES

The next few lines create the function that the server uses to serve up the frontend: This is a very basic fileserver that will either serve up a file in the same directory named index.html (our frontend) or throw an error if it cannot find or otherwise load it.

This last portion contains the meat of our app: here we define the players, handle incoming connections from clients, and send and receive data. The first thing we do here is define a variable to track which player we are dealing with. This is solely used at start to determine which player starts with the puck. The core of this bit is the connection event. Socket.io needs this in order to begin doing its thing so line 2 kicks that off by passing the incoming connection into the callback that runs on connection (*Note that the various emitters and receivers exist inside this connection).

Next we set a number for the player (line 5) and then on line 7 we emit that back to the client that just connected. This "emit" is important as it is a key part of using socket.io. What it does is emit an event we've named "player" back to the client where the client will handle it (we'll look at how when we get to the client side of things below).

The last part starts on line 9. This is a listener that will listen for an emit from the client named "volley". When it detects this emit it will trigger a callback function that will broadcast emit "return". A broadcast emit is one that is sent to all clients except for the current one.

That does it for the backend. Now let's take a look at the frontend.


Here is the entire frontend chunk of code. The HTML and CSS are self explanatory so I will only focus on the portions that pertain to socket.io. The first bit that matters here is the reference to socket.io.js on line 35. You may wonder how that path comes about. The simple answer is that socket.io itself is serving that up. Use that path and if socket.io is running you are good to go.

Next up is the first block of script tags. This contains our connection event and a couple of listeners that are waiting for emits from the backend: First, we create our connection to the web socket and assign it to a variable (line 1). Next we set up the connect listener and inside of it create a listener for the emit named "return" (lines 3-5) and a listener for the emit named "player" (lines 7-11). When the "return" event is emitted by the backend the client will trigger the jQuery animation defined in its callback, moving the puck down and onto the screen on the client. When the "player" event is emitted the code will check to see if the client should have the puck visible on their screen or not. A small bit of jQuery handles this. This "player" event is only emitted on client connection so it only comes into play when the client is first loaded, is refreshed, or the backend script is restarted.

The last piece of the puzzle is how to serve the puck to the other client: Here we have a jQuery click event attached to the puck element itself ('#target'). Line 1 simply sets up the standard document ready function for jQuery. We are then saying that upon click of the puck start an animation that moves the puck up off the top of the window (and fade it out for good measure). We then use the jQuery animate complete callback to trigger an emit named "volley" once the animation is done. If you look back at the full backend code you will see line 28 defines the listener for this event. That snippet of code does a broadcast emit (which, if you recall, emits to any client that it NOT the originating one) sending the "return" event to the other client (triggering the animation that brings the puck onto the screen).

No comments:

Post a Comment