Java NIO - 零拷贝

NIO零拷贝

  1. 使用传统的IO 方法传递一个大文件

  2. 使用NIO 零拷贝方式传递(transferTo)一个大文件

  3. 看看两种传递方式耗时时间分别是多少

传统IO方法

服务端代码

public class OldServer {
    public static void main(String[] args) {
        try {
            ServerSocket serverSocket = new ServerSocket(1212);
            System.out.println("服务端启动已启动......");
            while (true) {
                // 等待连接
                Socket socket = serverSocket.accept();
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        // 接收消息
                        try (InputStream inputStream = socket.getInputStream()){
                            byte[] result = new byte[1024];
                            while (true) {
                                int read = inputStream.read(result);
                                if (read == -1) {
                                    break;
                                }
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }).start();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

客户端代码

public class OldClient {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("localhost", 1212);
        OutputStream outputStream = socket.getOutputStream();
        // 文件大小为300MB
        File file = new File("D:\\电子书\\深入理解Apache Dubbo与实战.pdf");
        FileInputStream fileInputStream = new FileInputStream(file);
        byte[] buffer = new byte[(int) file.length()];
        long total = 0;
        long startTime = System.currentTimeMillis();
        while (true) {
            long readCount = fileInputStream.read(buffer);
            if (readCount == -1) {
                break;
            }
            total += readCount;
            outputStream.write(buffer);
        }
        outputStream.flush();
        System.out.println("发送总字节数: " + total + ", 耗时: " + (System.currentTimeMillis() - startTime));
        fileInputStream.close();

        socket.close();
    }
}

NIO零拷贝

服务端代码

public class NewIOServer {
    public static void main(String[] args) throws Exception {

        InetSocketAddress address = new InetSocketAddress(1313);
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        ServerSocket serverSocket = serverSocketChannel.socket();
        serverSocket.bind(address);
        System.out.println("服务端启动已启动......");
        //创建buffer
        ByteBuffer byteBuffer = ByteBuffer.allocate(4096);
        while (true) {
            SocketChannel socketChannel = serverSocketChannel.accept();
            int readcount = 0;
            while (-1 != readcount) {
                try {
                    readcount = socketChannel.read(byteBuffer);
                }catch (Exception ex) {
                   // ex.printStackTrace();
                    break;
                }
                //
                byteBuffer.rewind(); //倒带 position = 0 mark 作废
            }
        }
    }
}

客户端代码

public class NewIOClient {
    public static void main(String[] args) throws Exception {

        SocketChannel socketChannel = SocketChannel.open();
        socketChannel.connect(new InetSocketAddress("localhost", 1313));
        // 文件大小为300MB
        String filename = "D:\\电子书\\深入理解Apache Dubbo与实战.pdf";
        //得到一个文件channel
        FileChannel fileChannel = new FileInputStream(filename).getChannel();
        //准备发送
        long startTime = System.currentTimeMillis();
        // 在linux下,一次transferTo 就可以完成传输
        //transferTo 底层使用到零拷贝
        // long transferCount = fileChannel.transferTo(0, fileChannel.size(), socketChannel);

        //在windows下,一次ransferTo 只能发送8m , 就需要分段传输文件
        long total = 0;
        long position = 0; // 读取位置
        while (true) {
            long transferCount = fileChannel.transferTo(position, fileChannel.size(), socketChannel);
            if (transferCount > 0) {
                position = position + transferCount;
                total = total + transferCount;
            } else {
                break;
            }
        }

        System.out.println("发送的总的字节数 =" + total + " 耗时:" + (System.currentTimeMillis() - startTime));
        //关闭
        fileChannel.close();

    }
}
本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!