Repository: tokio-rs/axum
File: examples/websockets/src/main.rs (Rust)

Code before:
async fn handle_socket(mut socket: WebSocket, who: SocketAddr) {
    //send a ping (unsupported by some browsers) just to kick things off and get a response
    if let Ok(_) = socket.send(Message::Ping(vec![1, 2, 3])).await {
        println!("Pinged {}...", who);
    } else {
        println!("Could not ping {}!", who);
        return;
    }

    // receive single message form a client (we can either receive or send with socket)
    // this will likely be the Pong for our Ping or a hello.
    if let Some(msg) = socket.recv().await {
        if let Ok(msg) = msg {
            if process_message(msg, who) {
                return;
            }
        } else {
            println!("{} abruptly disconnected", who);
            return;
        }
    }

    // we can also send messages to client by simply sleeping,
    // since each client gets individual statemachine. Thus, waiting for this
    // client to finish getting his greetings does not prevent other clients form
    // connecting to server.
    for i in 1..5 {
        if socket
            .send(Message::Text(String::from(format!("Hi {} times!", i))))
            .await
            .is_err()
        {
            println!("client abruptly disconnected");
            return;
        }
        tokio::time::sleep(std::time::Duration::from_millis(100)).await;
    }

    // By splitting socket we can send and receive at the same time. In this example we will send
    // unsolicited messages to client based on some sort of server's internal event (i.e .timer).
    let (mut sender, mut receiver) = socket.split();

    // Spawn a task that will push 100 messages to the client (does not matter what client does)
    let mut send_task = tokio::spawn(async move {
        let mut i = 20;
        while i > 0 {
            // In any websocket error, break loop.
            if sender
                .send(Message::Text(format!("{} messages left...", i)))
                .await
                .is_err()

Review comment (suggestion):
I think this should be reworded a bit, you're not sending messages by sleeping.

Maybe it should say something about not worrying about blocking messages being sent to other connected clients.

Code after:

/// Actual websocket statemachine (one will be spawned per connection)
async fn handle_socket(mut socket: WebSocket, who: SocketAddr) {
    //send a ping (unsupported by some browsers) just to kick things off and get a response
    if let Ok(_) = socket.send(Message::Ping(vec![1, 2, 3])).await {
        println!("Pinged {}...", who);
    } else {
        println!("Could not send ping {}!", who);
        // no Error here since the only thing we can do is to close the connection.
        // If we can not send messages, there is no way to salvage the statemachine anyway.
        return;
    }

    // receive single message form a client (we can either receive or send with socket).
    // this will likely be the Pong for our Ping or a hello message from client.
    // waiting for message from a client will block this task, but will not block other client's
    // connections.
    if let Some(msg) = socket.recv().await {
        if let Ok(msg) = msg {
            if process_message(msg, who).is_break() {
                return;
            }
        } else {
            println!("client {} abruptly disconnected", who);
            return;
        }
    }

    // Since each client gets individual statemachine, we can pause handling
    // when necessary to wait for some external event (in this case illustrated by sleeping).
    // Waiting for this client to finish getting his greetings does not prevent other clients form
    // connecting to server and receiving their greetings.
    for i in 1..5 {
        if socket
            .send(Message::Text(String::from(format!("Hi {} times!", i))))
            .await
            .is_err()
        {
            println!("client {} abruptly disconnected", who);
            return;
        }
        tokio::time::sleep(std::time::Duration::from_millis(100)).await;
    }

    // By splitting socket we can send and receive at the same time. In this example we will send
    // unsolicited messages to client based on some sort of server's internal event (i.e .timer).
    let (mut sender, mut receiver) = socket.split();

    // Spawn a task that will push several messages to the client (does not matter what client does)
    let mut send_task = tokio::spawn(async move {
        let n_msg = 20;