Instant messaging has revolutionized how we communicate with each other, you could send a message to anyone anywhere in the world and they would instantly receive it.
Instant messaging applications like WhatsApp, Messenger and Instagram make use of real-time mode of communications which simply means that users can exchange information instantly or with negligible latency.
In this article, we will talk about how we can use Socket.IO to build a real-time chat application using Node.js as the backend and Flutter as the frontend. Let’s get started!
What is Socket.IO?
Here’s a formal definition from Socket.IO: Socket.IO is a library that enables real-time, bidirectional and event-based communication between the browser and the server. Now let’s take a look at how Socket.IO works…
Socket.IO establishes a connection between the client and the server using the WebSocket protocol, but if that fails, it falls back to using HTTP long-polling to make a successful connection.
Why Use Socket.IO Over HTTP Rest API?
HTTP is a request-response protocol, which means a client requests a data from a server, in return the server sends a response to that request. The downside to this is, for each message being sent, there's a new request-response being made, and since HTTP request-response protocol isn't a “keep-alive” (persistent) type of communication you'll have to make multiple HTTP connections when sending multiple messages resulting to high network latency thereby defeating the purpose of having a real-time chat application.
Socket.IO, on the other hand, operates on a persistent bi-directional data transfer system, which means that the connection is kept alive and messages are sent/received instantly or with negligible latency.
Let’s build out a project so you can see how we use Socket.IO to build a real-time chat application.
Setting up the Server (Node.js)
Step 1:
- Create a new folder with the desired name of your project, I'll name mine
socket_io_chat_server
. - Create a
package.json
file in the root of the folder - Now run
npm init
in your terminal, before you do this make sure you switch your current directory to that folder - Next, install the following packages through
npm
in your terminal.
\socket_io_chat_server> npm install http
\socket_io_chat_server> npm install socket.io
\socket_io_chat_server> npm install nodemon
\socket_io_chat_server> npm install express
Step 2:
Once all of our packages have been installed, we will create an app.js
file that will contain all of our Socket.IO configurations.
After you've created the app.js
file, copy and paste the code below into it.
const httpServer = require('http').createServer()
const socketIO = require('socket.io')(httpServer)
socketIO.on('connection', function (client) {
console.log('Connected...', client.id);
//listens for new messages coming in
client.on('message', function name(data) {
console.log(data);
socketIO.emit('message', data);
})
//listens when a user is disconnected from the server
client.on('disconnect', function () {
console.log('Disconnected...', client.id);
})
//listens when there's an error detected and logs the error on the console
client.on('error', function (err) {
console.log('Error detected', client.id);
console.log(err);
})
})
var port = process.env.PORT || 3000;
httpServer.listen(port, function (err) {
if (err) console.log(err);
console.log('Listening on port', port);
});
From the code above, we simply created a HTTP server using the http
module, we also created an instance of the Socket.IO module and passed in the httpServer
as an argument. Then we listen on the connection
event for incoming sockets and once a socket is connected to our app we log it on the console, same thing goes for the message
event, it listens for new messages coming in and logs it in the console.
Step 3:
In the previous step, notice that we called the listen
method on our httpServer
to listen for connections on our port. Now let’s start our server by running nodemon app.js
in our terminal.
You should see something like this:
The image above indicates that the server has been started and it’s listening on port 3000. Now that our server is up and running, let’s move on to setting up the client using Flutter as our frontend.
Setting up the Client (Flutter)
Step 1:
Create a new Flutter project by running the command below in your terminal:
flutter create socket_io_client_chat
Step 2:
Once this operation has finished, we need to add the socket_io_client
package as a dependency to our project. You can do that by running the following command in your terminal:
flutter pub add socket_io_client
This will add the Socket.IO client to your dependency in your pubspec.yaml
file.
I'll be leaving out the bulky UI codes of our Chat Screen for the sake of simplicity, and instead focus solely on how to initialize the Socket.IO client, listening to socket events and send messages using the client.
You can check out the full repo of this project on GitHub here 😉 . Don’t forget to star ⭐ the repo if you enjoy the article. Moving on…
Step 3: Initializing the Socket.IO Client
The code below is a simple implementation of initializing the Socket.IO client and listening to events received from the Server.
We use the
on
method on the Socket.IO object to listen to events from our Server.
...
Socket socket; //initalize the Socket.IO Client Object
@override
void initState() {
super.initState();
initializeSocket(); //--> call the initializeSocket method in the initState of our app.
}
@override
void dispose() {
socket.disconnect(); // --> disconnects the Socket.IO client once the screen is disposed
super.dispose();
}
void initializeSocket() {
socket =
io("http://127.0.0.1:3000/", <String, dynamic>{
"transports": ["websocket"],
"autoConnect": false,
});
socket.connect(); //connect the Socket.IO Client to the Server
//SOCKET EVENTS
// --> listening for connection
socket.on('connect', (data) {
print(socket.connected);
});
//listen for incoming messages from the Server.
socket.on('message', (data) {
print(data); //
});
//listens when the client is disconnected from the Server
socket.on('disconnect', (data) {
print('disconnect');
});
}
Step 4:
In the previous step we initialized our Socket.IO client, now let’s look at how to send messages with the client. To send messages to our server, we need to make use of the emit
method on the Socket.IO object.
The
emit
method is used to send events between the client and the server.
sendMessage(String message) {
socket.emit("message",
{
"id": socket.id,
"message": message, //--> message to be sent
"username": username,
"sentAt": DateTime.now().toLocal().toString().substring(0, 16),
},
);
}
From the code above, the emit
method on the Socket.IO object takes in two arguments, the event
name and the object
to be sent over to the Server. In our case, the event name here is message
and the object
we are to send are the properties of our message.
⚠️ Note
Before launching your Flutter application, run adb reverse tcp:3000 tcp:3000
in your terminal to resolve the issue of connecting to localhost on Android devices.
Conclusion
To wrap this up, Socket.IO makes it really simple for us to build a real-time chat application, and we have learnt what Socket.IO is, how it works, and why we choose Socket.IO over the traditional HTTP REST API. We also built a basic real-time chat application using Flutter as frontend and Node.js as the backend.
I hope you find this article useful and if you do please share. ☺️