JavaScript (ECMAScript) engine for building server side apps
http://nodejs.org/
Uses V8
Event/Callback driven - A callback function is registered for a specific event. When that event occurs the callback method is run.
// Use the http module: http://nodejs.org/api/http.html var http = require('http'); // http://nodejs.org/api/http.html#http_event_request function onRequest(req, res) { //req is an IncominMessage: http://nodejs.org/api/http.html#http_http_incomingmessage //res is a ServerResponse: http://nodejs.org/api/http.html#http_class_http_serverresponse res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('Hello World\n'); // Send a log message to the console console.log("Got a request " + req.url); } // Call the createServer method, passing in an anonymous callback function that will be called when a request is made var httpServer = http.createServer(onRequest); // Tell that server to listen on port 8080 httpServer.listen(8080); console.log('Server listening on port 8080');
To run, save this as "httpserver.js", upload it to your server and run it with:
node httpserver.js
A great write-up/explanation/tutorial for getting started with Node: http://www.nodebeginner.org/
Unfortunately, in the above example, the server will shutdown and stop running once you log out or stop it with cntrl-c. Forever is a node module that allows us to run a node server in the background.
Install the module:
npm install forver
Then run the server with it:
node_modules/forever/bin/forever start httpserver.js
List running servers (running using forever)
node_modules/forever/bin/forever list
Stop it
node_modules/forever/bin/forever stop httpserver.js
More information: http://blog.nodejitsu.com/keep-a-nodejs-server-up-with-forever
Socket.io is a node module that makes working with WebSockets easier. It also transparently supports older methods such as AJAX in the event that the browser doesn't support Web Sockets.
Before we do any programming, we should install the module in the directory we are going to use
npm install socket.io
Here is a basic example that we can go through:
// HTTP Portion var http = require('http'); var fs = require('fs'); // Using the filesystem module var httpServer = http.createServer(requestHandler); httpServer.listen(8080); function requestHandler(req, res) { // Read index.html fs.readFile(__dirname + '/index.html', // Callback function for reading function (err, data) { // if there is an error if (err) { res.writeHead(500); return res.end('Error loading index.html'); } // Otherwise, send the data, the contents of the file res.writeHead(200); res.end(data); } ); } // WebSocket Portion // WebSockets work with the HTTP server var io = require('socket.io').listen(httpServer); // Register a callback function to run when we have an individual connection // This is run for each individual user that connects io.sockets.on('connection', // We are given a websocket object in our function function (socket) { console.log("We have a new client: " + socket.id); // When this user "send" from clientside javascript, we get a "message" // client side: socket.send("the message"); or socket.emit('message', "the message"); socket.on('message', // Run this function when a message is sent function (data) { console.log("message: " + data); // Call "broadcast" to send it to all clients (except sender), this is equal to // socket.broadcast.emit('message', data); socket.broadcast.send(data); // To all clients, on io.sockets instead // io.sockets.emit('message', "this goes to everyone"); } ); // When this user emits, client side: socket.emit('otherevent',some data); socket.on('otherevent', function(data) { // Data comes in as whatever was sent, including objects console.log("Received: 'otherevent' " + data); }); socket.on('disconnect', function() { console.log("Client has disconnected"); }); } );
Save this file as whatever.js and upload it to a new directory on your server.
Here is the corresponding index.html file that should be uploaded to the same directory. (Don't forget to replace the SERVER_NAME with your server's name or address.):
<html> <head> <script src="/socket.io/socket.io.js"></script> <script> var socket = io.connect('http://SERVER_NAME:8080/'); socket.on('connect', function() { console.log("Connected"); }); // Receive a message socket.on('message', function(data) { console.log("Got: " + data); document.getElementById('messages').innerHTML += data; }); // Receive from any event socket.on('news', function (data) { console.log(data); }); var sendmessage = function() { var message = document.getElementById('message').value; console.log("Sending: " + message); // Send a messaage socket.send(message); }; var sendother = function() { var othermessage = document.getElementById('message').value; console.log("sending: " + othermessage); // Send any kind of data with a custom event //socket.emit('otherevent',{ othermessage: othermessage }); socket.emit('otherevent', othermessage); }; </script> </head> <body> <div id="messages"> No Messages Yet </div> <div> <input type="text" id="message" name="message"> <input type="button" value="message" onclick="sendmessage();"> <input type="button" value="other" onclick="sendother();"> </div> </body> </html>
More documentation and examples: https://github.com/LearnBoost/socket.io/wiki/Exposed-events and https://github.com/LearnBoost/socket.io/wiki/Exposed-events
How about using this with the JavaScript Canvas.
Starting with the HTML. (Don't forget to replace the SERVER_NAME with your server's name or address.) Let's call it canvas_socket.html:
<html> <head> <script type="text/javascript" src="/socket.io/socket.io.js"></script> <script type="text/javascript"> var socket = io.connect('http://SERVER_NAME:8080/'); socket.on('connect', function() { console.log("Connected"); }); // Receive from any event socket.on('othermouse', function (data) { console.log(data.x + " " + data.y); odraw(data.x,data.y); }); var sendmouse = function(xval, yval) { console.log("sendmouse: " + xval + " " + yval); socket.emit('othermouse',{ x: xval, y: yval }); }; /////////////// var canvas; var context; var initcanvas = function() { canvas = document.getElementById('mycanvas'); context = canvas.getContext('2d'); context.fillStyle="#FF0000"; context.fillRect(0,0,canvas.width,canvas.height); canvas.addEventListener('mousemove', function(evt) { console.log("mousemove " + evt.clientX + " " + evt.clientY); //evt.clientX is x but in the entire window, not the canvas //evt.clientY is y // Get the canvas bounding rect var canvasRect = canvas.getBoundingClientRect(); // Now calculate the mouse position values y = evt.clientY - canvasRect.top; // minus the starting point of the canvas rect x = evt.clientX - canvasRect.left; // minus the starting point of the canvas rect on the x axis console.log("mousemove x:" + x + " y:" + y); sendmouse(x,y); draw(x,y); }, false); }; var px = 0; var py = 0; var draw = function(xval,yval) { console.log("draw " + xval + " " + yval); context.beginPath(); // This is silly but it's what we have to do to get a random hex string context.strokeStyle='#000000'; context.moveTo(px,py); context.lineTo(xval,yval); context.stroke(); px = xval; py = yval; }; var opx = 0; var opy = 0; var odraw = function(xval,yval) { console.log("draw " + xval + " " + yval); context.beginPath(); // This is silly but it's what we have to do to get a random hex string context.strokeStyle='#000000'; context.moveTo(opx,opy); context.lineTo(xval,yval); context.stroke(); opx = xval; opy = yval; }; </script> </head> <body onload="initcanvas();"> <canvas width="600" height="600" id="mycanvas" /> </body> </html>
Now the javascript server portion:
// HTTP Portion var http = require('http'); var fs = require('fs'); // Using the filesystem module var httpServer = http.createServer(requestHandler); httpServer.listen(8080); function requestHandler(req, res) { // Read index.html fs.readFile(__dirname + '/canvas_socket.html', // Callback function for reading function (err, data) { // if there is an error if (err) { res.writeHead(500); return res.end('Error loading canvas_socket.html'); } // Otherwise, send the data, the contents of the file res.writeHead(200); res.end(data); } ); } // WebSocket Portion // WebSockets work with the HTTP server var io = require('socket.io').listen(httpServer); // Register a callback function to run when we have an individual connection // This is run for each individual user that connects io.sockets.on('connection', // We are given a websocket object in our function function (socket) { console.log("We have a new client: " + socket.id); // When this user emits, client side: socket.emit('otherevent',some data); socket.on('othermouse', function(data) { // Data comes in as whatever was sent, including objects console.log("Received: 'othermouse' " + data.x + " " + data.y); // Send it to all of the clients socket.broadcast.emit('othermouse', data); }); socket.on('disconnect', function() { console.log("Client has disconnected " + socket.id); }); } );