How to wait until tokio::TcpListener is ready to accept connections?


#1

I’m writing a code to test some custom handshake between two peers.

  1. Run TcpListener
  2. Wait until it initializes
  3. Process handshake
let mut core = Core::new().unwrap();
let handle = core.handle();

let addr: SocketAddr = "127.0.0.1:8000".parse().unwrap();
let handle_cloned = handle.clone();

let fut_stream = TcpListener::bind(&addr, &handle_cloned).unwrap();
let fut = fut_stream.incoming()
    .for_each(move |(stream, _)| {
        println!("connected");
        do_handshake(stream)
    })
    .map_err(...);

handle.spawn(fut);

let stream = TcpStream::connect(&addr, &handle_cloned);
let res =  core.run(stream);

This code leads to race condition and sometimes it prints “connected”, sometimes not.
And my question is how to ensure that TcpListener is running before I start connecting?


#2

I would spawn() the TcpStream as well, and then use a oneshot channel to signal completion of the test.

// as before
handle.spawn(fut);
let (tx_done, rx_done) = futures::oneshot();
let stream = TcpStream::connect(&addr, &handle_cloned);
// once `TcpStream` processing is done, signal completion
handle.spawn(stream.then(|_| tx_done.send(())));
// run the loop until completion is signaled
let res =  core.run(rx_done.then(|_| Ok::<_, ()>(())));

#3

Thank you, that helps.