Created
November 20, 2018 00:06
-
-
Save aludvik/a280dd5597ccaa4fc1d084b1209e138b to your computer and use it in GitHub Desktop.
Minimal example of doing non-blocking I/O with mio
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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