宣布tokio-io Crate
今天我们很高兴地宣布一个新的箱子和几个新工具 在Tokio堆栈中。这代表了许多并行的高潮 对各种零碎的更新,它们恰好便于降落 大约在同一时间!简而言之,改进是:
- 从tokio-core中提取的新tokio-io箱子,弃用了
  [
tokio_core :: io]模块。 - 将bytes crate引入tokio-io,允许抽象结束 缓冲和利用矢量I / O等基础功能。
 - 在“Sink”特征中添加一种新方法“close”,以表达优雅 关掉。
 
这些更改改进了Tokio的组织和抽象
几个长期存在的问题,应该为所有人提供稳定的基础
未来的发展。与此同时,这些变化并没有破坏
旧的io模块仍然以不推荐的形式提供。你可以开始全部使用了
这些箱子立即通过cargo update并使用最新的0.1。*
板条箱的版本!
让我们更深入地了解每个细节的变化,看看现在有什么可用。
 添加一个tokio-io箱子
 现有的[tokio_core :: io]模块提供了许多有用的抽象
但它们并不是tokio-core本身所特有的,也不是它的主要目的
tokio-io crate是提供这些核心实用程序而没有任何含义
运行时。使用tokio-io crates可以依赖于异步I / O语义
而不是将自己绑定到特定的运行时,例如tokio-core。
tokio-io crate旨在类似于[std :: io]标准
库模块在为异步提供通用抽象方面
生态系统。 tokio-io中提出的概念和特征是基础
对于在Tokio堆栈中完成的所有I / O.
tokio-io的主要内容是AsyncRead和AsyncWrite
特征。这两个特征是一种“分裂Io特征”并被选中
划分实现类似Tokio的读/写语义的类型(非阻塞
并通知未来的任务)。然后这些特征与[字节]集成
箱子提供一些方便的功能,并保留旧的功能,如
split。
我们还有机会刷新Codec特征
tokio-core crate到Encoder和Decoder特征,它们可以运行
bytes crate中的类型(EasyBuf在tokio-io中不存在,而且它是
现在在tokio-core中弃用了。这些类型允许您快速移动
字节流到Sink和Stream准备好接受成帧消息。
一个很好的例子就是使用tokio-io我们可以使用新的
length_delimited模块结合tokio-serde-json起床和
我们将在本文后面看到,立即使用JSON RPC服务器运行。
总的来说,tokio-io我们也能够重新审视几个小问题 API设计。这反过来使我们能够[关闭一大堆 问题] [关闭]反对tokio-core。我们觉得tokio-io是一个很好的补充 向前移动的Tokio堆栈。板条箱可以选择抽象 如果他们愿意的话,tokio-io不会像tokio-core那样拉动运行时间。
 集成bytes
 tokio-core的一个长期疣是它的EasyBuf字节缓冲区类型。
这种类型基本上就是它所说的锡(“简单”缓冲区),但是
遗憾的是,在高性能用例中通常不是您想要的。我们已经
长期以来希望有更好的抽象(以及更好的具体实现)
这里。
使用tokio-io你会发现crates.io上的bytes箱子更多
紧密集成并提供高性能所需的抽象
和“简单”缓冲同时。 bytes箱子的主要内容是
Buf和BufMut特征。这两个特征充当了能力
任意字节缓冲区(可读和可写)都是抽象的
在所有异步I / O对象上集成了read_buf和write_buf
现在。
除了用于抽象多种缓冲区的特性bytes crate
有两个高质量的这些特征实现,Bytes和
BytesMut类型(分别实现Buf和BufMut特征)。
简而言之,这些类型代表允许的引用计数缓冲区
以有效的方式对数据切片进行零拷贝提取。引导他们
还支持各种常见操作,如微小缓冲区(内联
存储),单一所有者(可以在内部使用Vec),共享所有者
不相交的视图(BytesMut),以及可能重叠视图的共享所有者
(Bytes)。
总的来说,我们希望的[字节]包是你的一站式字节缓冲区 抽象以及高质量的实现,让您运行 很快。我们很高兴看到bytes箱子里面有什么东西!
 添加Sink :: close
 我们最近登陆的最后一个重大变化是增加了一个新的 关于的方法
 添加 Sink::close
 我们最近登陆的最后一个重大变化是增加了一个新的
Sink特征的方法,close。 到目前为止还不是很好
关于以通用方式实现“优雅关闭”的故事,因为那里
没有干净的方式向水槽表明没有更多的物品被推入
它。 新的close方法正是为此目的而准备的。
close方法允许通知接收器不再有消息
推进去了。 然后,接收器可以借此机会刷新消息
否则执行协议特定的关闭。 例如,TLS连接
该点可能会启动关闭操作或代理连接
发出TCP级别的关闭。 通常情况下,这最终会触底到新的
[AsyncWrite :: shutdown]方法。
 添加 codec::length_delimited
 使用tokio-io登陆的一个大功能是添加
length_delimited模块(受Netty的启发
[LengthFieldBasedFrameDecoder])。 许多协议使用a来分隔帧
包含帧长度的帧头。 举一个简单的例子,拿一个
使用u32的帧头来划分帧有效载荷的协议。 每
电线上的框架看起来像这样:
+----------+--------------------------------+
| len: u32 |          frame payload         |
+----------+--------------------------------+
解析此协议可以轻松处理
// Bind a server socket
let socket = TcpStream::connect(
    &"127.0.0.1:17653".parse().unwrap(),
    &handle);
socket.and_then(|socket| {
    // Delimit frames using a length header
    let transport = length_delimited::FramedWrite::new(socket);
})
在上面的例子中,transport将是缓冲区的Sink + Stream
值,其中每个缓冲区包含帧有效负载。 这使得
将帧编码和解码为相当容易的值
像[serde]这样的东西。 例如,使用tokio-serde-json,我们可以
快速实现基于JSON的协议,其中每个帧都是长度
分隔,并使用JSON编码帧有效负载:
// Bind a server socket
let socket = TcpStream::connect(
    &"127.0.0.1:17653".parse().unwrap(),
    &handle);
socket.and_then(|socket| {
    // Delimit frames using a length header
    let transport = length_delimited::FramedWrite::new(socket);
    // Serialize frames with JSON
    let serialized = WriteJson::new(transport);
    // Send the value
    serialized.send(json!({
        "name": "John Doe",
        "age": 43,
        "phones": [
            "+44 1234567",
            "+44 2345678"
        ]
    }))
})
完整的例子就在这里。
length_delimited模块包含足够的配置设置来处理具有更复杂帧头的解析长度分隔帧,如HTTP / 2.0协议。
下一步是什么?
所有这些变化汇集在一起,关闭了期货和托克欧核心板条箱中的大量问题,我们认为Tokio正是我们喜欢的常见I / O和缓冲抽象的位置。一如既往,我们很乐意听到有关问题跟踪器的反馈,如果您发现问题,我们非常愿意合并PR!否则我们期待在实践中看到所有这些变化!
凭借tokio-core,tokio-io,tokio-service和tokio-proto的基础,Tokio团队期待着适应和实施更加雄心勃勃的协议,如HTTP / 2。我们正在与@seanmonstar和Hyper密切合作,以开发这些基础HTTP库。最后,我们希望在不久的将来扩展与HTTP和通用tokio服务实现相关的中间件故事。更多关于这个即将到来!