六.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)