文章目录

  • 一、 案例需求
  • 二、 传统 BIO 拷贝案例
  • 三、 零拷贝案例 服务器端
  • 四、 零拷贝案例 客户端
  • 五、 零拷贝案例 运行与分析

一、 案例需求


给出两个案例 , 一个是 使用普通的 BIO 模型 传输文件的案例 , 一个是 NIO + 零拷贝 传输文件案例 ;

传输 20M 的文件 , 对比二者的传输效率 ;

二、 传统 BIO 拷贝案例


服务器端使用 ServerSocket , 客户端使用 Socket , 在客户端将文件传输给服务器端 , 并统计整体的时间消耗 ;

1 . 服务器端代码 : 服务器端程序启动后 , 监听 8888 端口 , 等待客户端连接 , 客户端连接成功后 , 读取客户端上传的数据 , 服务器端将接收到的数据存储在 book2.pdf 文件中 ;

package kim.hsl.nio.zerocopy;import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;public class BIOFileServerDemo {public static void main(String[] args) {try {// 1. 创建服务器套接字, 并等待客户端连接ServerSocket serverSocket = new ServerSocket(8888);System.out.println("服务器启动,监听 8888 端口");//阻塞, 等待客户端连接请求 ( 此处是第一个阻塞点 )Socket socket = serverSocket.accept();long startTime = System.currentTimeMillis();System.out.println("客户端连接成功");// 2. 接收客户端传输的数据, 并写出到文件中InputStream inputStream = socket.getInputStream();FileOutputStream fileOutputStream = new FileOutputStream("book2.pdf");byte[] buffer = new byte[4096];int readLen;// 读取的字节个数大于等于 0 才写出数据while ( ( readLen = inputStream.read(buffer) ) >= 0 ) {// 写出数据到服务器fileOutputStream.write(buffer, 0, readLen);}System.out.println("文件传输完毕, 用时 : " + (System.currentTimeMillis() - startTime) + " ms");// 3. 关闭流socket.close();inputStream.close();fileOutputStream.close();} catch (IOException e) {e.printStackTrace();}}
}

2 . 客户端代码 : 客户端连接本地的 8888 端口服务器 , 读取本地的 book.pdf 文件 , 将其传输到服务器中 ;

package kim.hsl.nio.zerocopy;import java.io.FileInputStream;
import java.io.IOException;
import java.net.Inet4Address;
import java.net.InetSocketAddress;
import java.net.Socket;public class BIOFileClientDemo {public static void main(String[] args) {try {// 1. 客户端连接服务器Socket socket = new Socket();InetSocketAddress inetSocketAddress =new InetSocketAddress(Inet4Address.getLocalHost(), 8888);socket.connect(inetSocketAddress);System.out.println("客户端连接服务器成功, 开始传输文件 ...");long startTime = System.currentTimeMillis();// 2. 从文件中读取数据数据并传给服务器FileInputStream fileInputStream = new FileInputStream("book.pdf");byte[] buffer = new byte[4096];int readLen;// 读取的字节个数大于等于 0 才写出数据while ( ( readLen = fileInputStream.read(buffer) ) >= 0 ) {// 写出数据到服务器socket.getOutputStream().write(buffer, 0, readLen);}System.out.println("文件传输完毕, 用时 : " + (System.currentTimeMillis() - startTime) + " ms");//3. 关闭连接socket.close();fileInputStream.close();} catch (IOException e) {e.printStackTrace();}}
}

3 . 代码运行 :

① 开启服务器 : 服务器开启后阻塞监听 ;

② 开启客户端 : 客户端开启 , 连接服务器 , 连接成功后 , 将 20M 的文件传输给服务器 ; 客户端用时 229 ms 将数据传输给服务器 , 服务器用时 229 ms 接收并存储数据 , 二者时间基本差不多 ;


三、 零拷贝案例 服务器端


1 . 阻塞模式 与 非阻塞模式 :

① 非阻塞模式 : 如果调用 服务器套接字通道 ( ServerSocketChannel ) 的 configureBlocking(false) 方法设置非阻塞模式 , 就需要使用 Selector 注册通道 , 并监听事件 ;

② 阻塞模式 : 如果不经过上述设置 , 只需要使用如下方式 , 调用 accept() 方法阻塞等待客户端连接 , 如下用法 ; 这是 服务器套接字通道 ( ServerSocketChannel ) 的阻塞模式的使用 , 这里只是为了演示零拷贝机制 , 代码从简 ;

2 . 零拷贝操作 : 将 Socket 缓冲区中的数据直接拷贝到 内核缓冲区中 , 然后写出到文件 ;

使用零拷贝机制 , 一行代码完成 20M 的文件从 Socket 接收到硬盘文件写出操作 ;

fileChannel.transferFrom(socketChannel, 0, 1024 * 1024 * 32);

3 . 代码示例 :

package kim.hsl.nio.zerocopy;import java.io.FileOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.FileChannel;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;public class NIOFileServerDemo {public static void main(String[] args) {try {// 1. 创建并配置 服务器套接字通道 ServerSocketChannelServerSocketChannel serverSocketChannel = ServerSocketChannel.open();serverSocketChannel.socket().bind(new InetSocketAddress(8888));// 注意这里使用阻塞模式, 不调用该代码//serverSocketChannel.configureBlocking(false);// 2. 获取文件通道FileChannel fileChannel = new FileOutputStream("book2.pdf").getChannel();// 3. 阻塞等待SocketChannel socketChannel = serverSocketChannel.accept();// 4. 零拷贝核心操作fileChannel.transferFrom(socketChannel, 0, 1024 * 1024 * 32);// 5. 释放资源//socketChannel.close();//fileChannel.close();} catch (IOException e) {e.printStackTrace();}}
}

四、 零拷贝案例 客户端


1 . 零拷贝操作 : 调用 transferTo 方法 , 可以直接将硬盘中的文件传输到服务器端 ;

该方法传输速度快的原理就是使用了零拷贝的机制 , 从文件系统直接拷贝到目标通道 ;

fileChannel.transferTo(totalCount, 1024 * 1024 * 32, socketChannel)

2 . 代码示例 :

package kim.hsl.nio.zerocopy;import java.io.FileInputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.FileChannel;
import java.nio.channels.SocketChannel;public class NIOFileClientDemo {public static void main(String[] args) {try {// 1. 创建并配置 服务器套接字通道 ServerSocketChannelSocketChannel socketChannel = SocketChannel.open();socketChannel.connect(new InetSocketAddress("127.0.0.1", 8888));//socketChannel.configureBlocking(false);// 2. 从文件输入流中获取文件通道 ( FileChannel )FileChannel fileChannel = new FileInputStream("book.pdf").getChannel();long startTime = System.currentTimeMillis();// 3. 零拷贝传输数据, 注意记录每次拷贝的起始位置long transferLen;long totalCount = 0;// 使用零拷贝将文件数据传到服务器, 循环终止条件是传输结果小于等于 0while ( ( transferLen = fileChannel.transferTo(totalCount, 1024 * 1024 * 32, socketChannel) ) > 0 ) {totalCount += transferLen;}System.out.println("文件传输完毕, 用时 : " + (System.currentTimeMillis() - startTime) + " ms");// 4. 关闭连接socketChannel.close();fileChannel.close();} catch (IOException e) {e.printStackTrace();}}
}

五、 零拷贝案例 运行与分析


1 . 运行代码 :

① 首先运行服务器程序 : 启动即可 ;

② 再运行客户端程序 : 此时会记录整体的运行事件 , 此时从客户端向服务器端传输 20M 文件用时 68ms ;

2 . NIO 零拷贝 与 BIO 传统拷贝对比 :

BIO 传统拷贝 从客户端向服务器端传输 20MB 文件需要 229 ms ;

NIO 的零拷贝 从客户端向服务器端传输 20MB 文件需要 68ms ;

显然 NIO 零拷贝 传输效率有极大的提升 ;

【Netty】零拷贝案例 ( transferTo | transferFrom )相关推荐

  1. 【Netty】Netty零拷贝原理

    前言 理解零拷贝 零拷贝是Netty的重要特性之一,而究竟什么是零拷贝呢? WIKI中对其有如下定义: "Zero-copy" describes computer operati ...

  2. netty零拷贝之CompositeByteBuf

    目录 一. 背景简介 二. netty零拷贝 一.背景简介 在TCP网络数据传输过程中,数据包有可能被分割为独立的几个数据包进行发送,对于服务器接收端来说,单个的数据包是没有任何意义的,只有将这些数据 ...

  3. 80-15-020-原理-零拷贝-Netty零拷贝的原理

    1.概述 Netty 的零拷贝 1. 传统意义的拷贝 是在发送数据的时候,传统的实现方式是: File.read(bytes) Socket.send(bytes) 这种方式需要四次数据拷贝和四次上下 ...

  4. 四十七、Netty零拷贝

    零拷贝的定义 Zero-copy, 就是在操作数据时, 不需要将数据 buffer 从一个内存区域拷贝到另一个内存区域. 因为少了一次内存的拷贝, 因此 CPU 的效率就得到的提升. 在 OS 层面上 ...

  5. (七)Netty与零拷贝

    零拷贝基本介绍 零拷贝是网络编程的关键,很多性能优化都离不开 在Java程序中,常用的零拷贝有mmap(内存映射)和sendFile.那么,他们在OS里,到底是怎么样一个涉及?我们分析mmap和sen ...

  6. Netty、Kafka中的零拷贝技术到底有多牛?

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 来源:rrd.me/ggFBd 零拷贝,从字面意思理解就是数据不需 ...

  7. 深入探秘 Netty、Kafka 中的零拷贝技术!

    作者:ksfzhaohui 原文:juejin.im/post/5cad6f1ef265da039f0ef5df 零拷贝,从字面意思理解就是数据不需要来回的拷贝,大大提升了系统的性能.我们也经常在 J ...

  8. 理解Netty中的零拷贝(Zero-Copy)机制

    理解Netty中的零拷贝(Zero-Copy)机制 发表于2年前(2014-01-13 15:11)   阅读(10209) | 评论(12) 164人收藏此文章,我要收藏 赞29 12月12日北京O ...

  9. Netty编解码,粘包拆包及零拷贝

    Netty编解码 Netty涉及到编解码的组件有Channel.ChannelHandler.ChannelPipe等,先大概了解下这几个组件的作用. ChannelHandler ChannelHa ...

最新文章

  1. 首次使用gradle出现Could not find method leftShift() for arguments解决办法
  2. 学习JS的心路历程-参数传递方式(上)
  3. linux命令之tee,技术|为初学者介绍的 Linux tee 命令(6 个例子)
  4. linux命令行设置编码,编码样式-Linux命令行开关和参数是否有标准?
  5. 玩转oracle 11g(22):ora-01691和修改密码过期时间
  6. LeetCode 1765. 地图中的最高点(BFS)
  7. discuz 不能上传头像提示can not write to the data/tmp folder
  8. 直播App测试重点问题 - 服务器压力
  9. Element-UI中el-input输入值不显示
  10. c++ 暂停功能_苹果拥抱Rust,正在将C代码移植到Rust
  11. PS学习笔记6-选区工具
  12. android启动序列帧动画,关于 Lottie 动画的说明及应用
  13. 能上天的代码? NASA 火星无人机飞行控制系统开源了
  14. 笔记本电脑f11功能键_笔记本电脑按键功能详细图解_笔记本电脑键盘功能详细介绍是什么-win7之家...
  15. 金色传说:SAP-FICO-参考加权因素维护执行成本中心分配 KSV5/KSV3报错GA603:系统错误:集01018000D06表CCSS读出错
  16. 刺激越多效果越好?无创神经调控技术(rTMS)缓解疼痛
  17. 2023中央财经大学MTI英语翻译硕士专业考研成功经验分享
  18. 2023学习Linux云计算可以做什么岗位的工作?
  19. 甲骨文:“狂妄”的秘诀
  20. 中国电动汽车换电行业需求现状及未来发展规划报告2022-2028年版

热门文章

  1. Makefile 书写命令
  2. 前端 css+js实现返回顶部功能
  3. vue基础9(babel)
  4. FreeBSD 安装过程
  5. Java开发软件安装及配置
  6. jexus防止产生 *.core文件
  7. Android实例-MotionSensor加速度(XE8+小米2)
  8. 在VS.NET2003中无法新建C#项
  9. Salesforce - soql 多字段多值过滤查询思路
  10. jQuery练习---- 超简单的表格悬停变色Demo