WalzoneInterview Prep
📞 Interviewing soon? Practice with a realistic AI mock phone interview — it calls you, then scores you. First 15 min FREE →

Rust · Expert · question 72 of 100

How can you use the mio crate for high-performance, low-level I/O in Rust? Provide an example.?

📕 Buy this interview preparation book: 100 Rust questions & answers — PDF + EPUB for $5

The mio crate is a low-level I/O library for Rust that enables you to build fast and scalable networking applications. It provides an event-driven interface for non-blocking I/O based on the Reactor design pattern. Using mio, you can develop high-performance network servers and clients with minimal overhead and excellent resource utilization.

Here’s an example of how to use the ‘mio‘ crate to build a simple TCP server that handles multiple connections concurrently. The server listens on an IP address and port specified at runtime, and echoes back any data received from clients.

First, add ‘mio‘ to your project’s dependencies in ‘Cargo.toml‘:

    [dependencies]
    mio = "0.7"

Then, create a new Rust file called ‘main.rs‘ and add the following code:

    use mio::{Events, Interest, Poll, Token};
    use mio::net::{TcpListener, TcpStream};
    
    use std::net::SocketAddr;
    use std::collections::HashMap;
    use std::io::{Read, Write};
    
    const SERVER_TOKEN: Token = Token(0);
    
    struct Connection {
        socket: TcpStream,
        state: ConnectionState,
        buf: Vec<u8>,
    }
    
    impl Connection {
        fn new(socket: TcpStream) -> Connection {
            Connection {
                socket,
                state: ConnectionState::Reading,
                buf: Vec::new(),
            }
        }
        
        fn handle_read(&mut self, connections: &mut HashMap<Token, Connection>) {
            let mut buf = [0; 512];
            match self.socket.read(&mut buf) {
                Ok(0) => self.shutdown(connections),
                Ok(n) => {
                    self.buf.extend_from_slice(&buf[..n]);
                    self.state = ConnectionState::Writing;
                }
                Err(_) => {}
            }
        }
        
        fn handle_write(&mut self, connections: &mut HashMap<Token, Connection>) {
            match self.socket.write_all(&self.buf) {
                Ok(_) => {
                    self.state = ConnectionState::Reading;
                    self.buf.clear();
                }
                Err(_) => {}
            }
        }
        
        fn shutdown(&mut self, connections: &mut HashMap<Token, Connection>) {
            connections.remove(&self.socket.into());
        }
    }
    
    enum ConnectionState {
        Reading,
        Writing,
    }
    
    fn main() -> std::io::Result<()> {
        let addr: SocketAddr = "127.0.0.1:8080".parse().unwrap();
        let listener = TcpListener::bind(addr)?;
        
        let mut poll = Poll::new()?;
        let mut events = Events::with_capacity(1024);
        
        let mut connections = HashMap::new();
        
        poll.registry().register(&mut listener, SERVER_TOKEN, Interest::READABLE)?;
        
        loop {
            poll.poll(&mut events, None)?;
            
            for event in events.iter() {
                match event.token() {
                    SERVER_TOKEN => {
                        let (mut socket, addr) = listener.accept()?;
                        println!("Accepted connection from: {}", addr);
                        
                        let token = Token(connections.len() + 1);
                        poll.registry().register(&mut socket, token, Interest::READABLE)?;
                        
                        connections.insert(token, Connection::new(socket));
                    }
                    token => {
                        if let Some(connection) = connections.get_mut(&token) {
                            if event.is_readable() {
                                connection.handle_read(&mut connections);
                                poll.registry().reregister(&mut connection.socket, token, Interest::WRITABLE)?;
                            }
                            if event.is_writable() {
                                connection.handle_write(&mut connections);
                                poll.registry().reregister(&mut connection.socket, token, Interest::READABLE)?;
                            }
                        }
                    }
                }
            }
        }
    }

The above code initializes a listening ‘TcpListener‘ on the address ‘127.0.0.1:8080‘. Each new connection is registered with a unique ‘Token‘ and added to the ‘connections‘ HashMap. The event loop continuously polls for events and performs input/output operations on the connections as needed.

The ‘Connection‘ struct represents a single client connection with a socket and buffer for incoming and outgoing data. The connection state is tracked with an enum, and the ‘handle_read‘ and ‘handle_write‘ functions handle the corresponding I/O operations. When the connection is closed or disconnected, it is removed from the ‘connections‘ HashMap.

As you can see, using the ‘mio‘ crate allows for a performant and efficient way to handle multiple connections, without having to spawn a new thread for each incoming request.

Reading is step one. Saying it out loud is the interview. Our AI interviewer calls your phone and runs a realistic Rust interview — then scores it.
📞 Practice Rust — free 15 min
📕 Buy this interview preparation book: 100 Rust questions & answers — PDF + EPUB for $5

All 100 Rust questions · All topics