The basic steps will be:
- Install Node.js.
- Install Socket.IO.
- Create a directory for your project containing the backend code (title it app.js) and a file for the frontend (title it index.html).
- From the command line and inside the project directory start the server by typing: node app.js
- Open a browser and point it at: http://localhost:4000.
- Open a second browser and point it at the same URL.
- Click the puck and watch socket.io work its magic!
Setup
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
Backend
I'll present the full backend code and then go through explaining what everything does.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var app = require('http').createServer(handler) | |
, io = require('socket.io').listen(app) | |
, fs = require('fs'); | |
app.listen(4000); | |
function handler (req, res) { | |
fs.readFile(__dirname + '/index.html', | |
function (err, data) { | |
if (err) { | |
res.writeHead(500); | |
return res.end('Error loading index.html'); | |
} | |
res.writeHead(200); | |
res.end(data); | |
}); | |
} | |
var playernum = 0; | |
io.sockets.on('connection', function (socket) { | |
console.log('connected successfully...'); | |
playernum === 1 ? playernum = 0 : playernum++; | |
socket.emit('player', {'player': playernum}); | |
socket.on('volley', function (input) { | |
socket.broadcast.emit('return', {'data': 1}); | |
}); | |
}); |
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var app = require('http').createServer(handler) | |
, io = require('socket.io').listen(app) | |
, fs = require('fs'); | |
app.listen(4000); |
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.
warn - error raised: Error: listen EACCES
The next few lines create the function that the server uses to serve up the frontend:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function handler (req, res) { | |
fs.readFile(__dirname + '/index.html', | |
function (err, data) { | |
if (err) { | |
res.writeHead(500); | |
return res.end('Error loading index.html'); | |
} | |
res.writeHead(200); | |
res.end(data); | |
}); | |
} |
This last portion contains the meat of our app: here we define the players, handle incoming connections from clients, and send and receive data.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var playernum = 0; | |
io.sockets.on('connection', function (socket) { | |
console.log('connected successfully...'); | |
playernum === 1 ? playernum = 0 : playernum++; | |
socket.emit('player', {'player': playernum}); | |
socket.on('volley', function (input) { | |
socket.broadcast.emit('return', {'data': 1}); | |
}); | |
}); |
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.
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<title>socket.io Test</title> | |
<style> | |
html { | |
background: url('http://166.78.51.174/woodfloor.png') no-repeat 0 0 scroll; | |
background-color: #0C0C0C; | |
background-size: 100% 100%; | |
height: 100%; | |
width: 100%; | |
} | |
#target { | |
width: 200px; | |
height: 200px; | |
border-radius: 50%; | |
background-color: #4a90b8; | |
border: 1px solid #666; | |
box-shadow: 0px 10px 10px #333; | |
margin: 0 auto; | |
top: 60%; | |
left: 46%; | |
position: absolute; | |
} | |
h1 { | |
font-family: Century Gothic, sans-serif; | |
font-size: 200px; | |
text-align: center; | |
color: transparent; | |
text-shadow: 0px 0px 0px rgba(255, 255, 255, 0.15); | |
} | |
</style> | |
<script src="/socket.io/socket.io.js"></script> | |
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script> | |
<script> | |
var socket = io.connect('http://localhost:4000'); | |
socket.on('connect', function () { | |
socket.on('return', function (data) { | |
$('#target').animate({top: '500', opacity: 1}, 3000); | |
}); | |
socket.on('player', function(data){ | |
if(data.player !== 0){ | |
$('#target').css({"top": '-220px',"opacity": "0.1"}); | |
} | |
}); | |
}); | |
</script> | |
<script> | |
$(function () { | |
$('#target').click(function () { | |
$('#target').animate({top: '-200', opacity: 0.1}, 3000, function () { | |
socket.emit('volley', {'text': 'Shot made to server...'}); | |
}); | |
}); | |
}); | |
</script> | |
</head> | |
<body> | |
<h1>Litmusbox</h1> | |
<div id="target"></div> | |
</body> | |
</html> |
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:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var socket = io.connect('http://localhost:4000'); | |
socket.on('connect', function () { | |
socket.on('return', function (data) { | |
$('#target').animate({top: '500', opacity: 1}, 3000); | |
}); | |
socket.on('player', function(data){ | |
if(data.player !== 0){ | |
$('#target').css({"top": '-220px',"opacity": "0.1"}); | |
} | |
}); | |
}); |
The last piece of the puzzle is how to serve the puck to the other client:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$(function () { | |
$('#target').click(function () { | |
$('#target').animate({top: '-200', opacity: 0.1}, 3000, function () { | |
socket.emit('volley', {'text': 'Shot made to server...'}); | |
}); | |
}); | |
}); |
No comments:
Post a Comment