This tutorial will talk you through how to send messages from one client to another (via the server) using Socket.io.
For a detailed description of how to setup a Node.js project and develop a client-server web application using Express and Socket.io see my previous Socket Example.
As before, create a folder to store the project and change directory so you are in the project folder, e.g.
mkdir socket-example2
cd socket-example2
Run npm init .
which will help you to setup your project and create a package.json
file in your project folder.
Install Express and Socket.io:
npm install express --save
npm install socket.io --save
If the above commands fail and you are working from within IADT you may need to configure npm
to access the Internet via IADT's proxy server. To do this type:
npm config set proxy http://merlin:8080
Should you ever need to unset this, e.g. if you are working on a laptop and want to work at home, you can run:
npm config delete proxy
Create a server.js
file containing the following:
// server.js
var express = require('express');
var app = express();
var server = require('http').createServer(app);
var io = require('socket.io')(server);
app.use(express.static(__dirname + '/public'));
//redirect / to our index.html file
app.get('/', function(req, res,next) {
res.sendFile(__dirname + '/public/index.html');
});
io.on('connection', function(client) {
console.log('client connected');
});
//start our web server and socket.io server listening
server.listen(3000, function(){
console.log('listening on *:3000');
});
We will then add a function inside the Socket.io connection function above. This function will send an array containing the client IDs of all the clients connected to the server out to all the connected clients.
io.on('connection', function(client) {
console.log('client connected');
//when a new client connects
io.clients(function(error, clients){
if (error) throw error;
//send the list of clients out to all the clients
io.emit('clientList', clients);
});
});
Each client in Socket.io has a unique ID. So if there were 3 clients connected the clients
array above might contain [ 'wFCPkp1R33tO6sDOAAAA', 'mUNCRLPjy_-iGOeAAAAB', 'u38VgszMfSTMd-r6AAAC' ]
.
Create an index.html
file in a public
folder in your project folder containing:
<!DOCTYPE html>
<html>
<head>
<title>Socket.io Demo</title>
<meta charset="utf-8">
<link rel="stylesheet" href="styles.css">
</head>
<body>
<h1>Socket.io Client->Server->Client Demo</h1>
<p id="clientId"></p>
<p id="buttonCount">This client's button has been clicked 0 times.</p>
<div id="clients"></div>
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect();
//Once we're connected, display the client ID on the webpage
socket.on('connect', function(){
document.getElementById("clientId").innerHTML = "This client's ID is " + socket.id;
});
//Add a button for each client that is connected to the server
socket.on('clientList', function(data){
document.getElementById("clients").innerHTML = "";
for(var i = 0; i < data.length; i++){
//console.log(data[i]);
var btn = document.createElement("BUTTON");
btn.onclick = clientButtonClicked;
var textnode = document.createTextNode(data[i]);
btn.appendChild(textnode);
document.getElementById("clients").appendChild(btn);
}
});
//When any of the client buttons on this page are clicked
function clientButtonClicked(){
//Tell the server this button was clicked and send the client id along with the message
socket.emit('clientClicked', this.innerHTML);
}
</script>
</body>
</html>
This page connects to the Socket.io server we created above using var socket = io.connect();
. Once connected it will display this client's ID on the page.
//Once we're connected, display the client ID on the webpage
socket.on('connect', function(){
document.getElementById("clientId").innerHTML = "This client's ID is " + socket.id;
});
The next JS function handles the 'clientList'
message that is sent from the server. It loops through the array of client IDs and adds a button for each ID, e.g. 'wFCPkp1R33tO6sDOAAAA'
.
//Add a button for each client that is connected to the server
socket.on('clientList', function(data){
document.getElementById("clients").innerHTML = "";
for(var i = 0; i < data.length; i++){
//console.log(data[i]);
var btn = document.createElement("BUTTON");
btn.onclick = clientButtonClicked;
var textnode = document.createTextNode(data[i]);
btn.appendChild(textnode);
document.getElementById("clients").appendChild(btn);
}
});
Finally there is an onclick
handler for the buttons. When any of the buttons is clicked this sends a message to the server along with the client ID (e.g. 'wFCPkp1R33tO6sDOAAAA'
) from the button that was clicked.
//When any of the client buttons on this page are clicked
function clientButtonClicked(){
//Tell the server this button was clicked and send the client id along with the message
socket.emit('clientClicked', this.innerHTML);
}
We will now add another function inside the Socket.io connection function:
io.on('connection', function(client) {
console.log('client connected');
//when a new client connects
io.clients(function(error, clients){
if (error) throw error;
//send the list of clients out to all the clients
io.emit('clientList', clients);
console.log(clients);
});
//when the server receives clientClicked message, do this
client.on('clientClicked', function(id) {
//send a message to just the client whose button was clicked
io.to(id).emit('youWereClicked');
});
});
The 'clientClicked'
message handler triggers a message to be sent to just the client whose button was clicked, e.g. 'wFCPkp1R33tO6sDOAAAA'
.
Each client will keep track of how many times their button was clicked by any of the clients. We will do this by declaring and initialising a variable after connecting to the Socket.io server var clicked = 0;
.
We will then add a function that handles 'youWereClicked'
messages from the server. When a client is told that their button was clicked, they update their counter and display it on the page.
//what to do when the server tells this client their button was clicked by any of the clients
socket.on('youWereClicked', function(){
//console.log('clicked');
clicked++;
document.getElementById("buttonCount").innerHTML = "This client's button has been clicked " + clicked + ' times.';
});
Final code for index.html and server.js.
Following the above steps should result in the following behaviour:
Can you modify this example so that there is a text input field in the client, and when a user types a message in the input field and clicks a 'send to [clientid]' button the text they typed in is sent to just one of the other connected clients and displayed on the webpage? This would be a step towards a one-to-one direct messaging app.