Now we will implement the server, which will perform the task of relaying the messages, as already mentioned. Create a file in the routes
folder called sockets.js
and insert the following code into it:
var io = require('socket.io'), exports.initialize = function(server) { io = io.listen(server); io.sockets.on("connection", function(socket){ socket.send(JSON.stringify( {type:'serverMessage', message: 'Welcome to the most interesting chat room on earth!'})); socket.on('message', function(message){ message= JSON.parse(message); if(message.type == "userMessage"){ socket.broadcast.send(JSON.stringify(message)); message.type = "myMessage"; socket.send(JSON.stringify(message)); } }); }); };
In the first line of code (you must be familiar with this by now), we import the socket.io
module; we will identify this module by the io
variable.
Since socket.io works with the communication layer, we need to set it up to listen to the HTTP server. The HTTP server can only be accessed from the main application module, so we have to pass server
to our module before our module can do anything. Hence, we export a method called initialize
from our module, which will set up the socket.io server and also bind all the message handlers:
exports.initialize = function(server) { //work to do }
The initialize
method will accept the HTTP server
object as a parameter. This is required by socket.io:
io = io.listen(server);
On the first line of the method, we will pass the server to the socket.io module's listen
method. The server is an instance of the node HTTP server module; socket.io will configure various handlers on this server. This is the only boilerplate code required to set up socket.io. Next, we need to set up our message handler for socket.io messages.
The first event that our server will receive is a new connection from a new client. This is identified by the connection
event on the io.sockets
object and notifies our application that a new client has opened a new connection and all the protocol negotiation (transparent to us) has been completed and now we have a socket to communicate with this client:
io.sockets.on("connection", function(socket){ //Add other event handlers to the socket });
The connection
event handler will be triggered, passing along the socket that was just established. The socket is an event emitter that can trigger different events based on the messages it gets, and we will use this socket also to communicate with the client for which it was created. There are several events exposed, such as the connection
event to handle events on the server. Let's take a quick look at these events:
io.sockets.on('connection', function(socket) {})
: Initial connection from a client. The socket
argument should be used in further communication with the client.socket.on('message', function(message, callback) {})
: The message
handler is triggered when a message sent with socket.send
is received. The message
parameter is the message sent, and callback
is an optional acknowledgment function.socket.on('anything', function(data) {})
: The anything
event can be any event except the reserved events.socket.on('disconnect', function() {})
: This event is fired when the socket disconnects.Now that we have seen how to handle the socket events, let's see how we can send messages from the server to the client:
socket.send(JSON.stringify( {type:'serverMessage', message: 'Welcome to the most interesting chat room on earth!'}));
The socket.send
method will send the message on the socket, which will be triggering the message
event on the client. The message sent has to be a string, so we will use JSON.stringify
to send the data for the message as a string. Here our message has two parts, a type and a message.
One part of our task is over, we are now able to welcome the user. The next task is to handle the user messages when they come in. For this, we set a message
event handler on the socket:
socket.on('message', function(message){ message= JSON.parse(message); if(message.type == "userMessage"){ socket.broadcast.send(JSON.stringify(message)); message.type = "myMessage"; socket.send(JSON.stringify(message)); } });
Just like any other event connector, socket.on
will take two parameters, namely the event to handle and the event handler for it. In this case, unlike the io.sockets.on
event, this event handler will receive the message as the parameter and not the socket.
Since the message is a string, we will parse the message's JSON string to create a message
object. If this is a message sent by the user, this message will be of the type userMessage
, and that is what we check.
Now, we have to send out this message to all the connected users. For this, socket.io provides us with a broadcast
object. When we send the message using the broadcast
object, it will be sent to all the clients that are connected, except to the one for which this socket was created. The syntax for sending the message here is the same; the difference is that it is called on the broadcast
object, referred to as message flags in socket.io, instead of the socket itself.
Also, we want to send back the same content to the client that sent this message, but just change the type to myMessage
. For this, we send the message directly on the socket.
That's it. We have written the code for the server; but now we have to actually initialize this server. To do this, modify the server creation in app.js
to set the server
variable, as shown in the following code snippet:
var server = http.createServer(app).listen(app.get('port'), function(){ console.log("Express server listening on port " + app.get('port')); });
Now that we have modified the HTTP server, we can call the socket module's initialize
method, passing this server as a parameter to it. Add the following line to the end of app.js
:
require('./routes/sockets.js').initialize(server);