1 个不稳定版本
0.1.0 | 2024年1月14日 |
---|
#1505 在 异步
400KB
7K SLoC
verypoll - 只轮询IO。
lib.rs
:
verypoll是一个针对Rust的快速、低级I/O库,专注于非阻塞API和事件通知,以尽可能小的开销在操作系统抽象之上构建高性能I/O应用。
用法
使用verypoll首先创建一个Poll
实例,它从操作系统读取事件并将它们放入Events
。您可以使用它来处理来自操作系统的I/O事件。
更多详情请参阅Poll
。
指南
入门指南可在guide
模块中找到。
可用功能
可用功能在features
模块中描述。仅Unix扩展。Unix管道。
请参阅[new
]函数的文档。仅Windows扩展。
verypoll的可选功能。
本文档描述了verypoll中的可用功能。
verypoll默认只提供shell实现,当实际运行时会panic!
。要运行它需要操作系统支持,这可以通过激活os-poll
功能来实现。
这使得Poll
、Registry
和Waker
能够正常工作。
os-ext
启用额外的操作系统特定功能。这些功能可以在unix
和windows
模块中找到。
net
功能在net
模块中启用网络原语。
入门指南。
在这个指南中,我们将做以下事情:
- 创建一个
Poll
实例(并了解它是什么)。 - 注册一个[事件源]。
- 创建一个事件循环。
最后,您将拥有一个非常小但快速的TCP服务器,该服务器接受连接然后断开。
1. 创建一个Poll
实例
使用verypoll首先创建一个Poll
实例,它监视来自操作系统的事件并将它们放入Events
。这使得我们可以根据准备的操作执行I/O操作。
use verypoll::{Poll, Events};
fn main() -> std::io::Result<()> {
// Poll
允许轮询就绪事件。 let poll = Poll::new()?; // Events
是就绪 Event
集合,可以通过调用 Poll::poll
. let events = Events::with_capacity(128);
drop((poll, events));
Ok(())
}
For example if we're using a [`TcpListener`], we'll only want to
attempt to accept an incoming connection *iff* any connections are
queued and ready to be accepted. We don't want to waste our time if no
connections are ready.
[`TcpListener`]: ../net/struct.TcpListener.html
## 2. Registering event source
After we've created a [`Poll`] instance that monitors events from the OS
for us, we need to provide it with a source of events. This is done by
registering an [event source]. As the name “event source” suggests it is
a source of events which can be polled using a `Poll` instance. On Unix
systems this is usually a file descriptor, or a socket/handle on
Windows.
In the example below we'll use a [`TcpListener`] for which we'll receive
an event (from [`Poll`]) once a connection is ready to be accepted.
[event source]: ../event/trait.Source.html
// Create a `TcpListener`, binding it to `address`.
let mut listener = TcpListener::bind(address)?;
// Next we register it with `Poll` to receive events for it. The `SERVER`
// `Token` is used to determine that we received an event for the listener
// later on.
const SERVER: Token = Token(0);
poll.registry().register(&mut listener, SERVER, Interest::READABLE)?;
可以同时注册多个事件源(concurrently),因此可以一次监控多个源。
3. 创建事件循环
在创建了一个 Poll
实例,并使用它注册了一个或多个 事件源 后,我们可以对该实例进行事件轮询。轮询事件很简单,我们需要一个容器来存储事件:Events
,并且需要根据轮询到的事件执行一些操作(这部分取决于你,我们无法全部完成!)。如果我们以循环的方式执行这个过程,我们就得到了一个事件循环。
下面的示例展示了事件循环的实际应用,完成了我们的小型 TCP 服务器。
use std::io;
use std::time::Duration;
use verypoll::net::TcpListener;
use verypoll::{Poll, Token, Interest, Events};
fn main() -> io::Result<()> {
let mut poll = Poll::new()?;
let mut events = Events::with_capacity(128);
let address = "127.0.0.1:0".parse().unwrap();
let mut listener = TcpListener::bind(address)?;
const SERVER: Token = Token(0);
poll.registry().register(&mut listener, SERVER, Interest::READABLE)?;
// 启动事件循环。 loop { // 轮询操作系统事件,最长等待 100 毫秒。 poll.poll(&mut events, Some(Duration::from_millis(100)))?;
// Process each event.
for event in events.iter() {
// We can use the token we previously provided to `register` to
// determine for which type the event is.
match event.token() {
SERVER => loop {
// One or more connections are ready, so we'll attempt to
// accept them (in a loop).
match listener.accept() {
Ok((connection, address)) => {
println!("Got a connection from: {}", address);
drop(connection);
},
// A "would block error" is returned if the operation
// is not ready, so we'll stop trying to accept
// connections.
Err(ref err) if would_block(err) => break,
Err(err) => return Err(err),
}
}
_ => unreachable!(),
}
}
return Ok(());
}
fn would_block(err: &io::Error) -> bool { err.kind() == io::ErrorKind::WouldBlock }
}
依赖项
~0–9MB
~71K SLoC