六.Netty入门到超神系列-Java NIO零拷贝实战

Posted 墨家巨子@俏如来

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了六.Netty入门到超神系列-Java NIO零拷贝实战相关的知识,希望对你有一定的参考价值。

前言

这一章我们来操作一下NIO的零拷贝,这里我会先写代码样式一下传统IO数据拷贝场景下的耗时,然后再对比NIO场景下的考别耗时,通过耗时差异就能看到NIO零拷贝和传统IO拷贝的区别了。

传统IO拷贝

服务端

服务端主要是接收一下客户端传输过来的数据


//普通拷贝 - 服务端
public class SocketServer {

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

        //创建ServerSocket
        ServerSocket serverSocket = new ServerSocket(5000);

        while(true){
            //接待请求
            Socket socket = serverSocket.accept();

            //获取输入流
            DataInputStream dataInputStream = new DataInputStream(socket.getInputStream());

            //读取数据
            byte[] bytes = new byte[1024];

            int size = 0;

            while(true){
                try{
                    size = dataInputStream.read(bytes,0,bytes.length);
                    if(size == -1)break;
                    //读数据
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }
    }
}

客户端

客户端我们从磁盘读取一个文件,然后通过socket进行网络传输,并记录下消耗的时间

public class SocketClient {

    public static void main(String[] args) throws Exception {
        //创建Socket
        Socket socket = new Socket("127.0.0.1",5000);
        //文件输入流
        FileInputStream fileInputStream = new FileInputStream("D:\\\\idea-space\\\\idea-code\\\\netty-demo\\\\src\\\\main\\\\java\\\\cn\\\\itsource\\\\nio\\\\zerocopy\\\\img.zip");

        //输出流
        OutputStream outputStream = socket.getOutputStream();

        byte[] bytes = new byte[10240];
        int size = 0 ;
        int total = 0;
        long start = System.currentTimeMillis();

        //把文件中的数据写到socket
        while((size = fileInputStream.read(bytes)) != -1){
            total += size;
            outputStream.write(bytes);
        }
        //发送:1813047字节,耗时:16
        System.out.println("发送:"+total+"字节,耗时:"+(System.currentTimeMillis() - start));
        outputStream.close();
        fileInputStream.close();
        socket.close();
    }
}

我这里 发送:1813047字节,耗时:16

Java NIO拷贝

NIO拷贝要的事情和上面是一样的,只是代码有些差别

服务端

public class NIOCopyServer {

    public static void main(String[] args) throws IOException {
        //服务端
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        //监听
        serverSocketChannel.bind(new InetSocketAddress("127.0.0.1",6000));

        //缓冲区
        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);

        while (true){
            SocketChannel socketChannel = serverSocketChannel.accept();

            while(true){
                if(-1 != socketChannel.read(byteBuffer)){
                    break;
                }
                //为了重复利用buffer,考完一次就清空
                byteBuffer.clear();
            }
        }
    }
}

客户端

JAVA中的NIO零拷贝可以通过 fileChannel.transferTo 方法来实现 ,具体代码如下

public class NIOCopyClient {
    public static void main(String[] args) throws IOException {
        //创建通道
        SocketChannel socketChannel = SocketChannel.open();

        //链接服务端
        socketChannel.connect(new InetSocketAddress("127.0.0.1",6000));

        //文件输入流
        FileInputStream fileInputStream = new FileInputStream("D:\\\\idea-space\\\\idea-code\\\\netty-demo\\\\src\\\\main\\\\java\\\\cn\\\\itsource\\\\nio\\\\zerocopy\\\\img.zip");

        //读文件的通道
        FileChannel fileChannel = fileInputStream.getChannel();

        long start = System.currentTimeMillis();
		//transferTo 方法使用到了零拷贝技术
		//注意:在window上该方法一次只是支持8m数据拷贝,如果数据比价大,需要切片后多次传输
        long total = fileChannel.transferTo(0, fileChannel.size(), socketChannel);
        //发送字节数:1813047 ,耗时:4
        System.out.println("发送字节数:"+total+" ,耗时:"+(System.currentTimeMillis() - start));

        fileInputStream.close();
        fileChannel.close();
        socketChannel.close();
    }
}

同样的文件,同样的大小,发送字节数:1813047 , NIO 耗时:4 ,而传统IO拷贝 16,我这里文件2M不到,如果文件再大一点,效果更加明显。

文章到这就结束了,这一章比较简单,只是一个小案例,凑个篇数。当然点赞还是要求一下的,万一屏幕面前的大帅哥,或者大漂亮一不小心就一键三连了啦,那我就是熬夜到头发掉光,也出下章

以上是关于六.Netty入门到超神系列-Java NIO零拷贝实战的主要内容,如果未能解决你的问题,请参考以下文章

二.Netty入门到超神系列-Java NIO 三大核心(selector,channel,buffer)

三.Netty入门到超神系列-Java NIO 三大核心(selector,channel,buffer)

七.Netty入门到超神系列-Netty介绍和线程模型

三.Netty入门到超神系列-聊天室案例

八.Netty入门到超神系列-Netty入门程序

十.Netty入门到超神系列-基于Netty群聊系统