编写大型数据

    在我们的讨论传输(见4.2节)时,我们提到了 NIO 的“zero-copy(零拷贝)”功能,消除移动一个文件的内容从文件系统到网络堆栈的复制步骤。所有这一切发生在 Netty 的核心,因此所有所需的应用程序代码是使用 interface FileRegion 的实现,在 Netty 的API 文档中定义如下为一个通过 Channel 支持 zero-copy 文件传输的文件区域。

    下面演示了通过 zero-copy 将文件内容从 FileInputStream 创建 DefaultFileRegion 并写入 使用 Channel

    Listing 8.11 Transferring file contents with FileRegion

    1. 获取 FileInputStream
    2. 创建一个新的 DefaultFileRegion 用于文件的完整长度
    3. 发送 DefaultFileRegion 并且注册一个 ChannelFutureListener
    4. 处理发送失败

    这个关键是 interface ChunkedInput,实现如下:

    清单 8.12 演示了使用 ChunkedStream,实现在实践中最常用。
    所示的类被实例化一个 File 和一个 SslContext。当 initChannel() 被调用来初始化显示的处理程序链的通道。

    当通道激活时,WriteStreamHandler 从文件一块一块的写入数据作为ChunkedStream。最后将数据通过 SslHandler 加密后传播。

    1. private final File file;
    2. private final SslContext sslCtx;
    3. public ChunkedWriteHandlerInitializer(File file, SslContext sslCtx) {
    4. this.file = file;
    5. this.sslCtx = sslCtx;
    6. @Override
    7. protected void initChannel(Channel ch) throws Exception {
    8. ChannelPipeline pipeline = ch.pipeline();
    9. pipeline.addLast(new SslHandler(sslCtx.createEngine()); //1
    10. pipeline.addLast(new ChunkedWriteHandler());//2
    11. pipeline.addLast(new WriteStreamHandler());//3
    12. }
    13. public final class WriteStreamHandler extends ChannelInboundHandlerAdapter { //4
    14. public void channelActive(ChannelHandlerContext ctx) throws Exception {
    15. super.channelActive(ctx);
    16. ctx.writeAndFlush(new ChunkedStream(new FileInputStream(file)));
    17. }
    18. }
    1. 添加 SslHandler 到 ChannelPipeline.
    2. 添加 ChunkedWriteHandler 用来处理作为 ChunkedInput 传进的数据
    3. 当连接建立时,WriteStreamHandler 开始写文件的内容
    4. 当连接建立时,channelActive() 触发使用 ChunkedInput 来写文件的内容 (插图显示了 FileInputStream;也可以使用任何 InputStream )

    ChunkedInput
    所有被要求使用自己的 ChunkedInput 实现,是安装ChunkedWriteHandler 在管道中

    在本节中,我们讨论

    • 如何采用zero-copy(零拷贝)功能高效地传输文件

    在下一节中我们将研究几种不同方法来序列化 POJO。