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?