[Tokio] Restarting TcpListener


#1

I’m trying to shutdown a TcpListener in tokio and rebind it to the same port but it seems that tokio doesn’t free the listening socket even after Core has been dropped? Here is the code I tried:

    {
        let mut core = Core::new().unwrap();
        let handle = core.handle();
        let tcp = TcpListener::bind(&SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8081), &handle).unwrap();
        let sockets = tcp.incoming();
        let job = sockets.for_each(|(socket, addr)| {
            Ok(())
        }).then(|_| Ok(()));
        let run = Timeout::new(Duration::from_secs(3), &core.handle()).unwrap();
        handle.spawn(job);
        core.run(run);
    }
    { // This part is just a copy paste of the previous block
        let mut core = Core::new().unwrap();
        let handle = core.handle();
        let tcp = TcpListener::bind(&SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8081), &handle).unwrap();
        let sockets = tcp.incoming();
        let job = sockets.for_each(|(socket, addr)| {
            Ok(())
        }).then(|_| Ok(()));
        let run = Timeout::new(Duration::from_secs(3), &core.handle()).unwrap();
        handle.spawn(job);
        core.run(run);
    }

I received a panic in the second TcpListener::bind with the message: “Only one usage of each socket address (protocol/network address/port) is normally permitted.”. Perhaps somebody can enlighten me if it is a problem with the code? Thank you.


#2

This is on Windows, I suppose, where libstd doesn’t set SO_REUSEADDR on server sockets (current master). On Unix-like systems, that options is necessary to reuse the same address:port combo while the old socket is in TIME_WAIT. Not knowing Windows, I’m not sure why the option isn’t used, and whether an equivalent exists.


#3

This is indeed on Windows. Killing the process and immediately launching it again, binding to the same socket seem to work fine though. Wouldn’t TIME_WAIT prevent it in this case too?