12个版本
0.2.2 | 2024年3月27日 |
---|---|
0.2.0 | 2023年11月6日 |
0.1.1 | 2023年5月31日 |
0.1.0 | 2023年3月9日 |
0.0.4 | 2021年12月6日 |
#646 in 异步
402 每月下载次数
用于 4 个crate(3个直接使用)
780KB
17K SLoC
Monoio Compat
为 monoio 提供兼容包装器。
使用示例
use monoio_compat::{AsyncReadExt, AsyncWriteExt, TcpStreamCompat};
#[monoio::main]
async fn main() {
const ADDRESS: &str = "127.0.0.1:50009";
let (mut oneshot_tx, mut oneshot_rx) = local_sync::oneshot::channel::<()>();
let server = async move {
let listener = monoio::net::TcpListener::bind(ADDRESS).unwrap();
oneshot_rx.close();
let (conn, _) = listener.accept().await.unwrap();
let mut compat_conn = unsafe { TcpStreamCompat::new(conn) };
let mut buf = [0u8; 10];
compat_conn.read_exact(&mut buf).await.unwrap();
buf[0] += 1;
compat_conn.write_all(&buf).await.unwrap();
};
let client = async {
oneshot_tx.closed().await;
let conn = monoio::net::TcpStream::connect(ADDRESS).await.unwrap();
let mut compat_conn = unsafe { TcpStreamCompat::new(conn) };
let mut buf = [65u8; 10];
compat_conn.write_all(&buf).await.unwrap();
compat_conn.read_exact(&mut buf).await.unwrap();
assert_eq!(buf[0], 66);
};
monoio::join!(client, server);
}
在使用此crate之前,请阅读以下说明。
重要说明
即使有此包装器,TcpStreamCompat
仍然与 Tokio IO 接口不完全兼容。
用户必须确保一旦使用 poll_write
和 poll_read
发送了一块数据,它将继续被使用,直到调用返回 Ready
。否则,将发送旧数据。
我们实现了一个简单的检查机制,以确保在 poll_write
之间数据相同。但为了性能,我们只检查数据长度,这并不足够。可能会造成不稳定性。
例如,基于此包装器运行的 h2
服务器将失败。在 h2
内,它将尝试使用 poll_write
发送一个数据帧,如果它得到 Pending
,它将假设数据尚未发送。如果有另一个优先级更高的数据帧,它将使用新的帧 poll_write
。但旧数据帧将使用我们的包装器发送。
核心问题是由于 poll
-like 接口与异步系统调用的不兼容引起的。
TcpStreamCompat 和 TcpStreamCompatUnsafe
TcpStreamCompat: 首先将数据复制到所有者缓冲区,然后构建保存未来。如果用户不遵循规则,它将引发恐慌。
TcpStreamCompatUnsafe: 只保存用户提供的缓冲区指针和长度。它不会复制数据,因此比 TcpStreamCompat 更高效。但如果用户不遵循规则,它将导致内存损坏。
依赖关系
~3–12MB
~126K SLoC