How to correctly drop TcpStream when splitted?

Hi everyone !

I have a server and I want to implement the way to correctly shutdown the sockets before listener will be dropped. This is what I do for now:

async fn start() -> AnyResult<()> {
    let port = 12345;
    let listener = TcpListener::bind(format!("127.0.0.1:{}", port)).await?;

    let mut connections: BTreeMap<SessionKey, Connection> = BTreeMap::new();

    loop {
        tokio::select! {
            Ok((socket, addr)) = listener.accept() => {
                let (input_sender, input_receiver) = mpsc::channel::<Vec<u8>>(BUFFER_SIZE);
                let (output_sender, output_receiver) = mpsc::channel::<Vec<u8>>(BUFFER_SIZE);

                tokio::spawn(async move {
                    join_all(vec![
                        Self::handle_read(input_sender),
                        Self::handle_input(input_receiver, output_sender),
                        Self::handle_write(output_receiver),
                    ]).await;
                });
            },
            _ = signal::ctrl_c() => {
                for (_, mut connection) in connections.iter_mut() {
                    connection.socket.shutdown().await?;
                }

                break;
            },
        }
    }

    Ok(())
}

This works fine, but I need to split my socket to use reader and writer in different tasks:

let (rx, tx) = socket.into_split();

and now I am not sure if tx.shutdown().await will be enough to correctly close each connection or I still need to keep origin socket to call shutdown() on it ?

and also another related question: how to correctly drop listener here ? or it will be dropped correctly on ctrl + C ?

Calling shutdown on the writer half is sufficient.

1 Like