WebSockets constitute one of the most useful features of HTML5. The protocol, standardized in RFC 6455, has come to dominate the web of today. It has been designed to be used by web servers and browsers. As of today, almost all major browsers support it. WebSockets' handshakes are interpreted by HTTP servers as an Upgrade request.
Node.js is a software platform used to build scalable network applications. It uses javascript as it's scripting language and is built around Google V8 Javascript engine. It contains a built-in HTTP server library and hence can be used to build web servers without the use of any additional software. Node.js also comes with a very useful package manager called 'npm'.
In this post, I present a simple echo server using Node.js and a client using WebSockets and make them communicate. This is presented using the Mac OS X 10.8 operating system, but it should work without issues on any other operating systems as well.
Step 2: Install the websocket package using npm. Open the terminal and type
$sudo npm install websocket
This installs the websocket package. The result should correspond to the following screenshot.
Step 3: Now implement the web server. Copy paste the following code into a file called 'ws_server.js'.
#!/usr/bin/env node
var WebSocketServer = require('websocket').server;
var http = require('http');
var server = http.createServer(function(request, response) {
console.log((new Date()) + ' Received request for ' + request.url);
response.writeHead(404);
response.end();
});
server.listen(8080, function() {
console.log((new Date()) + ' Server is listening on port 8080');
});
wsServer = new WebSocketServer({
httpServer: server,
// You should not use autoAcceptConnections for production
// applications, as it defeats all standard cross-origin protection
// facilities built into the protocol and the browser. You should
// *always* verify the connection's origin and decide whether or not
// to accept it.
autoAcceptConnections: false
});
function originIsAllowed(origin) {
// put logic here to detect whether the specified origin is allowed.
return true;
}
wsServer.on('request', function(request) {
if (!originIsAllowed(request.origin)) {
// Make sure we only accept requests from an allowed origin
request.reject();
console.log((new Date()) + ' Connection from origin ' + request.origin + ' rejected.');
return;
}
var connection = request.accept('echo-protocol', request.origin);
console.log((new Date()) + ' Connection accepted.');
connection.on('message', function(message) {
if (message.type === 'utf8') {
console.log('Received Message: ' + message.utf8Data);
connection.sendUTF(message.utf8Data);
}
else if (message.type === 'binary') {
console.log('Received Binary Message of ' + message.binaryData.length + ' bytes');
connection.sendBytes(message.binaryData);
}
});
connection.on('close', function(reasonCode, description) {
console.log((new Date()) + ' Peer ' + connection.remoteAddress + ' disconnected.');
});
});
Step 4: Run the server using the command
$node ws_server.js
The server should be running and listening on port 8080 and the result should correspond to the screenshot below.
Step 5: It's time to write the client! We use HTML and javascript to write the client. Copy the following HTML code into a file called 'client.html'.
<!DOCTYPE html>
<html lang="en">
<head>
<title>WebSocket Echo Client</title>
<meta charset="UTF-8" />
<script>
"use strict";
// Initialize everything when the window finishes loading
window.addEventListener("load", function(event) {
var status = document.getElementById("status");
var url = document.getElementById("url");
var open = document.getElementById("open");
var close = document.getElementById("close");
var send = document.getElementById("send");
var text = document.getElementById("text");
var message = document.getElementById("message");
var socket;
status.textContent = "Not Connected";
url.value = "ws://localhost:8080";
close.disabled = true;
send.disabled = true;
// Create a new connection when the Connect button is clicked
open.addEventListener("click", function(event) {
open.disabled = true;
socket = new WebSocket(url.value, "echo-protocol");
socket.addEventListener("open", function(event) {
close.disabled = false;
send.disabled = false;
status.textContent = "Connected";
});
// Display messages received from the server
socket.addEventListener("message", function(event) {
message.textContent = "Server Says: " + event.data;
});
// Display any errors that occur
socket.addEventListener("error", function(event) {
message.textContent = "Error: " + event;
});
socket.addEventListener("close", function(event) {
open.disabled = false;
status.textContent = "Not Connected";
});
});
// Close the connection when the Disconnect button is clicked
close.addEventListener("click", function(event) {
close.disabled = true;
send.disabled = true;
message.textContent = "";
socket.close();
});
// Send text to the server when the Send button is clicked
send.addEventListener("click", function(event) {
socket.send(text.value);
text.value = "";
});
});
</script>
</head>
<body>
Status: <span id="status"></span><br />
URL: <input id="url" /><br />
<input id="open" type="button" value="Connect" />
<input id="close" type="button" value="Disconnect" /><br />
<input id="send" type="button" value="Send" />
<input id="text" /><br />
<span id="message"></span>
</body>
</html>
Step 6: Open 'client.html' using the browser and click on 'connect'. A connection would be established with the running server. Type a message and click on 'send' to send it to the server. The result should be as in the screenshot below.
References:
1. Colin Ihrig's blogs on the same topic.
2. Github repositories of WebSocket-related stuff.
3. Wikipedia.