|
|
|
|
# Mio – Metal IO
|
|
|
|
|
|
|
|
|
|
Mio is a fast, low-level I/O library for Rust focusing on non-blocking APIs and
|
|
|
|
|
event notification for building high performance I/O apps with as little
|
|
|
|
|
overhead as possible over the OS abstractions.
|
|
|
|
|
|
|
|
|
|
[![Crates.io][crates-badge]][crates-url]
|
|
|
|
|
[![MIT licensed][mit-badge]][mit-url]
|
|
|
|
|
[![Build Status][azure-badge]][azure-url]
|
|
|
|
|
[![Build Status][cirrus-badge]][cirrus-url]
|
|
|
|
|
|
|
|
|
|
[crates-badge]: https://img.shields.io/crates/v/mio.svg
|
|
|
|
|
[crates-url]: https://crates.io/crates/mio
|
|
|
|
|
[mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg
|
|
|
|
|
[mit-url]: LICENSE
|
|
|
|
|
[azure-badge]: https://dev.azure.com/tokio-rs/Tokio/_apis/build/status/tokio-rs.mio?branchName=master
|
|
|
|
|
[azure-url]: https://dev.azure.com/tokio-rs/Tokio/_build/latest?definitionId=2&branchName=master
|
|
|
|
|
[cirrus-badge]: https://api.cirrus-ci.com/github/tokio-rs/mio.svg
|
|
|
|
|
[cirrus-url]: https://cirrus-ci.com/github/tokio-rs/mio
|
|
|
|
|
|
|
|
|
|
**API documentation**
|
|
|
|
|
|
|
|
|
|
* [master](https://tokio-rs.github.io/mio/doc/mio/)
|
|
|
|
|
* [v0.7](https://docs.rs/mio/^0.7)
|
|
|
|
|
* [v0.6](https://docs.rs/mio/^0.6)
|
|
|
|
|
|
|
|
|
|
This is a low level library, if you are looking for something easier to get
|
|
|
|
|
started with, see [Tokio](https://tokio.rs).
|
|
|
|
|
|
|
|
|
|
## Usage
|
|
|
|
|
|
|
|
|
|
To use `mio`, first add this to your `Cargo.toml`:
|
|
|
|
|
|
|
|
|
|
```toml
|
|
|
|
|
[dependencies]
|
|
|
|
|
mio = "0.7"
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Next we can start using Mio. The following is quick introduction using
|
|
|
|
|
`TcpListener` and `TcpStream`. Note that `features = ["os-poll", "net"]` must be
|
|
|
|
|
specified for this example.
|
|
|
|
|
|
|
|
|
|
```rust
|
|
|
|
|
use std::error::Error;
|
|
|
|
|
|
|
|
|
|
use mio::net::{TcpListener, TcpStream};
|
|
|
|
|
use mio::{Events, Interest, Poll, Token};
|
|
|
|
|
|
|
|
|
|
// Some tokens to allow us to identify which event is for which socket.
|
|
|
|
|
const SERVER: Token = Token(0);
|
|
|
|
|
const CLIENT: Token = Token(1);
|
|
|
|
|
|
|
|
|
|
fn main() -> Result<(), Box<dyn Error>> {
|
|
|
|
|
// Create a poll instance.
|
|
|
|
|
let mut poll = Poll::new()?;
|
|
|
|
|
// Create storage for events.
|
|
|
|
|
let mut events = Events::with_capacity(128);
|
|
|
|
|
|
|
|
|
|
// Setup the server socket.
|
|
|
|
|
let addr = "127.0.0.1:13265".parse()?;
|
|
|
|
|
let mut server = TcpListener::bind(addr)?;
|
|
|
|
|
// Start listening for incoming connections.
|
|
|
|
|
poll.registry()
|
|
|
|
|
.register(&mut server, SERVER, Interest::READABLE)?;
|
|
|
|
|
|
|
|
|
|
// Setup the client socket.
|
|
|
|
|
let mut client = TcpStream::connect(addr)?;
|
|
|
|
|
// Register the socket.
|
|
|
|
|
poll.registry()
|
|
|
|
|
.register(&mut client, CLIENT, Interest::READABLE | Interest::WRITABLE)?;
|
|
|
|
|
|
|
|
|
|
// Start an event loop.
|
|
|
|
|
loop {
|
|
|
|
|
// Poll Mio for events, blocking until we get an event.
|
|
|
|
|
poll.poll(&mut events, None)?;
|
|
|
|
|
|
|
|
|
|
// Process each event.
|
|
|
|
|
for event in events.iter() {
|
|
|
|
|
// We can use the token we previously provided to `register` to
|
|
|
|
|
// determine for which socket the event is.
|
|
|
|
|
match event.token() {
|
|
|
|
|
SERVER => {
|
|
|
|
|
// If this is an event for the server, it means a connection
|
|
|
|
|
// is ready to be accepted.
|
|
|
|
|
//
|
|
|
|
|
// Accept the connection and drop it immediately. This will
|
|
|
|
|
// close the socket and notify the client of the EOF.
|
|
|
|
|
let connection = server.accept();
|
|
|
|
|
drop(connection);
|
|
|
|
|
}
|
|
|
|
|
CLIENT => {
|
|
|
|
|
if event.is_writable() {
|
|
|
|
|
// We can (likely) write to the socket without blocking.
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if event.is_readable() {
|
|
|
|
|
// We can (likely) read from the socket without blocking.
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Since the server just shuts down the connection, let's
|
|
|
|
|
// just exit from our event loop.
|
|
|
|
|
return Ok(());
|
|
|
|
|
}
|
|
|
|
|
// We don't expect any events with tokens other than those we provided.
|
|
|
|
|
_ => unreachable!(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Features
|
|
|
|
|
|
|
|
|
|
* Non-blocking TCP, UDP
|
|
|
|
|
* I/O event queue backed by epoll, kqueue, and IOCP
|
|
|
|
|
* Zero allocations at runtime
|
|
|
|
|
* Platform specific extensions
|
|
|
|
|
|
|
|
|
|
## Non-goals
|
|
|
|
|
|
|
|
|
|
The following are specifically omitted from Mio and are left to the user
|
|
|
|
|
or higher-level libraries.
|
|
|
|
|
|
|
|
|
|
* File operations
|
|
|
|
|
* Thread pools / multi-threaded event loop
|
|
|
|
|
* Timers
|
|
|
|
|
|
|
|
|
|
## Platforms
|
|
|
|
|
|
|
|
|
|
Currently supported platforms:
|
|
|
|
|
|
|
|
|
|
* Android
|
|
|
|
|
* DragonFly BSD
|
|
|
|
|
* FreeBSD
|
|
|
|
|
* Linux
|
|
|
|
|
* NetBSD
|
|
|
|
|
* OpenBSD
|
|
|
|
|
* Solaris
|
|
|
|
|
* Windows
|
|
|
|
|
* iOS
|
|
|
|
|
* macOS
|
|
|
|
|
|
|
|
|
|
There are potentially others. If you find that Mio works on another
|
|
|
|
|
platform, submit a PR to update the list!
|
|
|
|
|
|
|
|
|
|
Mio can handle interfacing with each of the event systems of the aforementioned
|
|
|
|
|
platforms. The details of their implementation are further discussed in the
|
|
|
|
|
`Poll` type of the API documentation (see above).
|
|
|
|
|
|
|
|
|
|
The Windows implementation for polling sockets is using the [wepoll] strategy.
|
|
|
|
|
This uses the Windows AFD system to access socket readiness events.
|
|
|
|
|
|
|
|
|
|
[wepoll]: https://github.com/piscisaureus/wepoll
|
|
|
|
|
|
|
|
|
|
## Community
|
|
|
|
|
|
|
|
|
|
A group of Mio users hang out on [Discord], this can be a good place to go for
|
|
|
|
|
questions.
|
|
|
|
|
|
|
|
|
|
[Discord]: https://discord.gg/tokio
|
|
|
|
|
|
|
|
|
|
## Contributing
|
|
|
|
|
|
|
|
|
|
Interested in getting involved? We would love to help you! For simple
|
|
|
|
|
bug fixes, just submit a PR with the fix and we can discuss the fix
|
|
|
|
|
directly in the PR. If the fix is more complex, start with an issue.
|
|
|
|
|
|
|
|
|
|
If you want to propose an API change, create an issue to start a
|
|
|
|
|
discussion with the community. Also, feel free to talk with us in Discord.
|
|
|
|
|
|
|
|
|
|
Finally, be kind. We support the [Rust Code of Conduct](https://www.rust-lang.org/policies/code-of-conduct).
|