六.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不到,如果文件再大一点,效果更加明显。

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

  • 27
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

墨家巨子@俏如来

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值