Building a Real-Time Chat Application with WebSockets and Rust
The Importance of Real-Time Chat Applications
Real-time chat applications allow users to communicate with each other in real time through text, voice, or video. This type of app allows for more immediate messaging than other types of communication such as email or IM. There are several reasons why chat applications must work in real time:
- Improved performance: More immediate communication allows for more natural conversation
- Greater responsiveness: Real-time functionality results in improved user experience
- Superior reliability: With real-time functionality there’s less opportunity for messages to be lost or delayed
Introduction to WebSockets
WebSockets enables two-way communication between the client and server in real-time chat applications. Using Rust to build the WebSocket server will enable the server to handle a large number of connections without slowing down. This is due to Rust’s speed and reliability.
Getting Started
First, let’s review some prerequisites:
- Rust: Ensure you have Rust installed on your computer. If you don’t have it, use the following command to install it:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
- React: Ensure that your environment is ready for React development; use one of the below commands to install React if you don’t already have it: ( commands omitted for brevity )
Next, run the following commands to verify that everything is installed and working properly:
Designing the Real-Time Chat App Architecture
Let’s create some design architecture for our real-time chat application. We’ll build a simple server; our application’s architecture will cover the following features:
- Chat: between two users via direct messaging
- Typing indicator: notifies the recipient when a user starts typing a chat to them
- User status: indicates whether the user is online or offline
This architecture is very simple and easy to follow. It consists of just a few components:
- WebSocket server: This is the most important component of our application; it handles all the communication between clients and rooms
- Room manager: This component is responsible for managing all the rooms in our application. It will create, update, and delete rooms. This component will be on the HTTP server
- User manager: This component is responsible for managing all the users in our application. It will create, update, and delete users. This component will be on the HTTP server as well
- Message manager: This component is responsible for managing all the messages in our application. It will create, update, and delete messages. This component one will be on the WebSocket server and the HTTP server. It will be used to store incoming messages from WebSockets and retrieve all messages already in the database when the user opens the chat room via the Rest API
Building the WebSocket Server in Rust
There are many packages we can use to write a WebSocket server in Rust. For this tutorial, we’ll use Actix Web; it is a mature package and is easy to use.
To start, create a Rust project using the following command:
cargo new chat_app --bin
Add this package to the Cargo.toml file:
[dependencies]
actix-web = "3"
actix-cors = "0.5"
actix-files = "0.4"
diesel = { version = "1.4", features = ["sqlite"] }
serde_json = "1"
Install diesel_cli; we’ll use this as our ORM:
cargo install diesel_cli
Here’s how the structure of the project should look:
chat_app/
Cargo.toml
src/
main.rs
static/
ui/
Now, let’s write the entry point for our WebSocket server:
use actix_web::{web, App, HttpServer, Responder};
use actix_cors::Cors;
use actix_files::{Files, NamedFile};
use diesel::prelude::*;
async fn index() -> impl Responder {
NamedFile::open_async("static/index.html").await.unwrap()
}
#[actix_web::main]
async fn main() -> std::io::Result<> {
HttpServer::new(|| {
App::new()
.wrap(Cors::new().supports_credentials(true))
.service(web::resource("/").route(web::get().to(index)))
.service(Files::new("/static", "static").show_files_listing())
})
.bind("127.0.0.1:8080")?
.run()
.await
}
Next, let’s make routes for our server…