一、 案例需求
给出两个案例 , 一个是 使用普通的 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 接收并存储数据 , 二者时间基本差不多 ;