Number of TIME_WAIT connections is less than expected

20 Views Asked by At

I have learned why TIME_WAIT is a good thing to have and want to ensure every of my connections stay in TIME_WAIT when it should. I wrote a small script (attached at the end) to perform the following things:

  • Spawn a TCP listener on port 8000
  • In a forever loop, connect to the listener, then shutdown the connection
    • The listener recv on the accepted connections to ensure they are always closed by the other end

What I expect is there are more and more <random port> -> 8000 connections stays in TIME_WAIT state, until 60s when the first TIME_WAIT timeout, or the number of connections reaches 32768 which is the maximum number of concurrent TIME_WAIT connections according to tcp man page.

However, what I observed (through netstat --tcp -n | grep TIME_WAIT | wc -l) is that the number of TIME_WAIT connections keep stable around 14116, and never increase anymore. The number happens to equal (61000 - 32768) / 2 (the default ephemeral port range), making me can't help to build connection between them but has no clue.

The script

use std::net::SocketAddr;

use tokio::{
    io::AsyncReadExt,
    net::{TcpListener, TcpStream},
    spawn,
};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let listener = TcpListener::bind("0.0.0.0:8000").await?;
    let listen_session = spawn(async move {
        let mut buf = [0; 1];
        loop {
            let (mut conn, _) = listener.accept().await?;
            conn.read(&mut buf).await?;
        }
    });
    let connect_session = async {
        for i in 0.. {
            let stream = TcpStream::connect(SocketAddr::from(([127, 0, 0, 1], 8000))).await?;
            println!("{i} {stream:?}");
            drop(stream)
        }
        Ok(())
    };
    tokio::select! {
        result = listen_session => result?,
        result = connect_session => result,
    }
}

By the way there's another problem about my understanding of TIME_WAIT. From this well-known blog I learned that TIME_WAIT is mainly for preventing delayed packets to interfere with the following irrelevant connections with the same quad-tuple. My question is that why only the actively-closing side need to concern about this? Isn't that also possible for a delayed packet in the opposite direction arrives the passive-closing side?

0

There are 0 best solutions below