前言
这一章我们来操作一下NIO的零拷贝,这里我会先写代码样式一下传统IO数据拷贝场景下的耗时,然后再对比NIO场景下的考别耗时,通过耗时差异就能看到NIO零拷贝和传统IO拷贝的区别了。
传统IO拷贝
服务端
服务端主要是接收一下客户端传输过来的数据
//普通拷贝 - 服务端publicclassSocketServer { publicstaticvoidmain(String[] args) throwsException { //创建ServerSocketServerSocketserverSocket=newServerSocket(5000); while(true){ //接待请求Socketsocket=serverSocket.accept(); //获取输入流DataInputStreamdataInputStream=newDataInputStream(socket.getInputStream()); //读取数据byte[] bytes=newbyte[1024]; intsize=0; while(true){ try{ size=dataInputStream.read(bytes,0,bytes.length); if(size==-1)break; //读数据 }catch (Exceptione){ e.printStackTrace(); } } } } }
客户端
客户端我们从磁盘读取一个文件,然后通过socket进行网络传输,并记录下消耗的时间
publicclassSocketClient { publicstaticvoidmain(String[] args) throwsException { //创建SocketSocketsocket=newSocket("127.0.0.1",5000); //文件输入流FileInputStreamfileInputStream=newFileInputStream("D:\\idea-space\\idea-code\\netty-demo\\src\\main\\java\\cn\\itsource\\nio\\zerocopy\\img.zip"); //输出流OutputStreamoutputStream=socket.getOutputStream(); byte[] bytes=newbyte[10240]; intsize=0 ; inttotal=0; longstart=System.currentTimeMillis(); //把文件中的数据写到socketwhile((size=fileInputStream.read(bytes)) !=-1){ total+=size; outputStream.write(bytes); } //发送:1813047字节,耗时:16System.out.println("发送:"+total+"字节,耗时:"+(System.currentTimeMillis() -start)); outputStream.close(); fileInputStream.close(); socket.close(); } }
我这里 发送:1813047字节,耗时:16
Java NIO拷贝
NIO拷贝要的事情和上面是一样的,只是代码有些差别
服务端
publicclassNIOCopyServer { publicstaticvoidmain(String[] args) throwsIOException { //服务端ServerSocketChannelserverSocketChannel=ServerSocketChannel.open(); //监听serverSocketChannel.bind(newInetSocketAddress("127.0.0.1",6000)); //缓冲区ByteBufferbyteBuffer=ByteBuffer.allocate(1024); while (true){ SocketChannelsocketChannel=serverSocketChannel.accept(); while(true){ if(-1!=socketChannel.read(byteBuffer)){ break; } //为了重复利用buffer,考完一次就清空byteBuffer.clear(); } } } }
客户端
JAVA中的NIO零拷贝可以通过 fileChannel.transferTo 方法来实现 ,具体代码如下
publicclassNIOCopyClient { publicstaticvoidmain(String[] args) throwsIOException { //创建通道SocketChannelsocketChannel=SocketChannel.open(); //链接服务端socketChannel.connect(newInetSocketAddress("127.0.0.1",6000)); //文件输入流FileInputStreamfileInputStream=newFileInputStream("D:\\idea-space\\idea-code\\netty-demo\\src\\main\\java\\cn\\itsource\\nio\\zerocopy\\img.zip"); //读文件的通道FileChannelfileChannel=fileInputStream.getChannel(); longstart=System.currentTimeMillis(); //transferTo 方法使用到了零拷贝技术//注意:在window上该方法一次只是支持8m数据拷贝,如果数据比价大,需要切片后多次传输longtotal=fileChannel.transferTo(0, fileChannel.size(), socketChannel); //发送字节数:1813047 ,耗时:4System.out.println("发送字节数:"+total+" ,耗时:"+(System.currentTimeMillis() -start)); fileInputStream.close(); fileChannel.close(); socketChannel.close(); } }
同样的文件,同样的大小,发送字节数:1813047 , NIO 耗时:4 ,而传统IO拷贝 16,我这里文件2M不到,如果文件再大一点,效果更加明显。
文章到这就结束了,这一章比较简单,只是一个小案例,凑个篇数。当然点赞还是要求一下的,万一屏幕面前的大帅哥,或者大漂亮一不小心就一键三连了啦,那我就是熬夜到头发掉光,也出下章