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

Code before:
        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()
            {
                break;
            }

            tokio::time::sleep(std::time::Duration::from_millis(300)).await;
            i -= 1;
        }
        if i == 0 {
            println!("Sending close to {}...", who);
            if let Err(e) = sender
                .send(Message::Close(Some(CloseFrame {
                    code: 1000,
                    reason: Cow::from("Goodbye"),
                })))
                .await
            {
                println!("Could not send Close due to {}, probably it is ok?", e);
            }
        }
        i
    });

    // This second task will receive messages from client and print them on server console
    let mut recv_task = tokio::spawn(async move {
        let mut cnt = 0;
        while let Some(Ok(msg)) = receiver.next().await {
            cnt += 1;

Review comment (suggestion):
```suggestion
                return;
```

That way you don't need to check `i` after the loop because you'll return from the task.

Code after:

    // 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;
        for i in 0..n_msg {
            // In case of any websocket error, we exit.
            if sender
                .send(Message::Text(format!("Server message {} ...", i)))
                .await
                .is_err()
            {
                return i;
            }

            tokio::time::sleep(std::time::Duration::from_millis(300)).await;
        }

        println!("Sending close to {}...", who);
        if let Err(e) = sender
            .send(Message::Close(Some(CloseFrame {
                code: axum::extract::ws::close_code::NORMAL,
                reason: Cow::from("Goodbye"),
            })))
            .await
        {
            println!("Could not send Close due to {}, probably it is ok?", e);
        }
        n_msg
    });

    // This second task will receive messages from client and print them on server console