Tutorial
This tutorial demonstrates how to set up a basic server using the Rust web framework axum, along with axum-socket-io for real-time communication.
You can find the full source code for this tutorial here.
Setup
- Initialize a new Rust project
cargo new <project-name>
cd <project-name>
- Add dependencies to
Cargo.toml
:
[dependencies]
tokio = { version = "1", features = ["full"] }
axum = "0.7"
axum-socket-io = "0.1"
Server Implementation
In the src/socket.rs
file, write the following code:
use axum_socket_io::SocketIo;
use std::net::SocketAddr;
pub async fn handle_socket(mut socket: SocketIo, addr: SocketAddr) {
println!("A user connected: {addr:#?}");
while let Ok(_ev) = socket.recv().await {
// ...
}
println!("user disconnected: {addr:#?}");
}
In the src/main.rs
file, write the following code:
mod socket;
use axum::{
extract::ConnectInfo,
response::{Html, IntoResponse},
routing::get,
Router,
};
use axum_socket_io::SocketIoUpgrade;
use std::{io, net::SocketAddr};
use tokio::net::TcpListener;
#[tokio::main]
async fn main() -> io::Result<()> {
let app = Router::new()
.route("/", get(|| async { Html(include_str!("../index.html")) }))
.route("/socket", get(ws_handler));
println!("listening on http://127.0.0.1:3000");
axum::serve(
TcpListener::bind("127.0.0.1:3000").await?,
app.into_make_service_with_connect_info::<SocketAddr>(),
)
.await
}
async fn ws_handler(ws: SocketIoUpgrade, info: ConnectInfo<SocketAddr>) -> impl IntoResponse {
ws.on_upgrade(16, move |socket| socket::handle_socket(socket, info.0))
}
Client Code
In your project directory, create an index.html
file with the following
content:
<script type="module">
import { SocketIo } from "https://esm.sh/client-socket-io@0.1.0";
const socket = new SocketIo("ws://127.0.0.1:3000/socket");
await socket.connect();
alert("Hello, World!")
</script>
Running the Project
- Build and run the Rust server:
cargo run
- Go to
http://127.0.0.1:3000
, and you should seeHello, World!