Crate socketioxide

source ·
Expand description

Socket.IO server implementation as a tower layer in Rust.

It integrates with any framework that based on tower/hyper, such as:

Usage with axum

use axum::routing::get;
use axum::Server;
use serde::{Serialize, Deserialize};
use socketioxide::{Namespace, SocketIoLayer};
use serde_json::Value;

#[derive(Debug, Serialize, Deserialize)]
struct MyData {
  pub name: String,
  pub age: u8,
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {

    println!("Starting server");

    let ns = Namespace::builder()
        .add("/", |socket| async move {
            println!("Socket connected on / namespace with id: {}", socket.sid);

            // Add a callback triggered when the socket receive an 'abc' event
            // The json data will be deserialized to MyData
            socket.on("abc", |socket, data: MyData, bin, _| async move {
                println!("Received abc event: {:?} {:?}", data, bin);
                socket.bin(bin).emit("abc", data).ok();
            });

            // Add a callback triggered when the socket receive an 'acb' event
            // Ackknowledge the message with the ack callback
            socket.on("acb", |_, data: Value, bin, ack| async move {
                println!("Received acb event: {:?} {:?}", data, bin);
                ack.bin(bin).send(data).ok();
            });
            // Add a callback triggered when the socket disconnect
            // The reason of the disconnection will be passed to the callback
            socket.on_disconnect(|socket, reason| async move {
                println!("Socket.IO disconnected: {} {}", socket.sid, reason);
            });
        })
        .add("/custom", |socket| async move {
            println!("Socket connected on /custom namespace with id: {}", socket.sid);
        })
        .build();

    let app = axum::Router::new()
        .route("/", get(|| async { "Hello, World!" }))
        .layer(SocketIoLayer::new(ns));

    Server::bind(&"0.0.0.0:3000".parse().unwrap())
        .serve(app.into_make_service())
        .await?;

    Ok(())
}

Modules

  • Adapters are responsible for managing the state of the server. When a socket joins or leaves a room, the adapter is responsible for updating the state. The default adapter is the LocalAdapter, which stores the state in memory. Other adapters can be made to share the state between multiple servers.
  • Extensions used to store extra data in each socket instance.

Structs

Enums