Skip to content

Instantly share code, notes, and snippets.

@aludvik
Created November 20, 2018 00:06
Show Gist options
  • Save aludvik/a280dd5597ccaa4fc1d084b1209e138b to your computer and use it in GitHub Desktop.
Save aludvik/a280dd5597ccaa4fc1d084b1209e138b to your computer and use it in GitHub Desktop.
Minimal example of doing non-blocking I/O with mio
extern crate mio;
use mio::{Events, Ready, Poll, PollOpt, Token};
use mio::net::{TcpListener, TcpStream};
use std::io::{Read, Write};
use std::str;
const LISTENER: Token = Token(0);
const CLIENT: Token = Token(1);
const SERVER: Token = Token(2);
fn assert_ready(events: &Events, token: Token, readiness: Ready) {
assert_eq!(
Some(readiness),
events.iter().filter(|event| event.token() == token).map(|event| event.readiness()).next(),
);
}
fn main() {
// Create a non-blocking listener
let listener = TcpListener::bind(&"127.0.0.1:0".parse().unwrap()).unwrap();
let addr = listener.local_addr().unwrap();
// Connect a non-blocking stream to the listener
let mut client = TcpStream::connect(&addr).unwrap();
// Poll the status of the two sockets
let mut events = Events::with_capacity(4);
let poll = Poll::new().unwrap();
poll.register(&listener, LISTENER, Ready::readable(), PollOpt::level()).unwrap();
poll.register(&client, CLIENT, Ready::readable() | Ready::writable(), PollOpt::level()).unwrap();
poll.poll(&mut events, None).unwrap();
for (i, event) in events.iter().enumerate() {
println!("event({}) = {:?}", i, event);
}
// Ensure that the LISTENER is ready to be read (meaning a client is trying to connect)
assert_ready(&events, LISTENER, Ready::readable());
// Ensure that the CLIENT is ready to write (meaning the client can send data)
assert_ready(&events, CLIENT, Ready::writable());
// Accept the client, we can unwrap() here without worrying about WouldBlock because we just
// saw that the listener was ready to be read. (In general, this isn't true and getting
// WouldBlock should be handled here).
let (mut server, _) = listener.accept().unwrap();
// Send from the client since it is ready to write
assert_ne!(client.write("hello".as_bytes()).unwrap(), 0);
// IMPORTANT!!! Need to flush here for this example, or else the SERVER socket will not show
// that it is ready to be read due to OS buffering.
client.flush().unwrap();
// Register the new connection and poll it.
poll.register(&server, SERVER, Ready::readable() | Ready::writable(), PollOpt::level()).unwrap();
poll.poll(&mut events, None).unwrap();
for (i, event) in events.iter().enumerate() {
println!("event({}) = {:?}", i, event);
}
// Assert that there is data to read on the SERVER that was sent by CLIENT, sometimes this
// still fails if the OS is slow to deliver the flushed client data
assert_ready(&events, SERVER, Ready::readable() | Ready::writable());
// Create a buffer to store the "hello" message;
let mut buf: [u8; 5] = [0; 5];
// Read the data sent by the client and print
server.read(&mut buf).unwrap();
println!("{}", str::from_utf8(&buf).unwrap());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment