赞
踩
Data Memory Access 直接内存拷贝
KernelBuffer 内核缓冲区
CpuCopy 通过CPU拷贝
UserBuffer 用户缓冲区
SocketBuffer Socket缓冲区
ProtocolEngine 协议栈
用户空间共享内核区数据,减少 1 次CPU拷贝
数据不经过用户态,直接从内核缓冲区进入到Socket缓冲区
将2.1的从内核缓冲区到Socket缓冲区数据拷贝,修改为关键信息拷贝:length、offset 等
由于只拷贝文件描述信息,数据量很小,消耗低,可以忽略;相当于直接将数据拷贝到协议栈
package com.example.netty.io.zerocopy; import java.io.DataInputStream; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; /** * Description: 传统IO服务端 * * @Author: zhx & moon hongxu_1234@163.com * @Date: 2022-01-23 18:19 * @version: V1.0.0 */ public class OldCopyServer { public static void main(String[] args) throws IOException { ServerSocket serverSocket = new ServerSocket(7800); while (true){ Socket socket = serverSocket.accept(); DataInputStream dataInputStream = new DataInputStream(socket.getInputStream()); byte[] buffer = new byte[4096]; long readCount; long total = 0; while (-1!=(readCount = dataInputStream.read(buffer,0,buffer.length))){ total += readCount; } //此处会体现为整字节 即最后Total为4096整倍数 System.out.println("读取字节数: " + total); } } }
package com.example.netty.io.zerocopy; import java.io.DataOutputStream; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.net.Socket; /** * Description: 传统IO客户端 * * @Author: zhx & moon hongxu_1234@163.com * @Date: 2022-01-23 18:07 * @version: V1.0.0 */ public class OldCopyClient { public static void main(String[] args) throws IOException { traditionalCopy("night.jpg"); } /** * 发送数据 * @param fileName * @throws IOException */ public static void traditionalCopy(String fileName) throws IOException { //定义Socket Socket socket = new Socket("127.0.0.1",7800); //定义文件输入流 InputStream inputStream = new FileInputStream(fileName); //定义数据输出流 DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream()); //定义缓冲字节数组 byte[] buffer = new byte[4096]; //定义读取字节数和总字节数 long readCount; long total = 0; //记录开始时间 long start = System.currentTimeMillis(); //循环读写 while ((readCount = inputStream.read(buffer)) >= 0){ total += readCount; dataOutputStream.write(buffer); } //打印结果 System.out.println("发送总字节数:" + total + " 耗时(MS):" + (System.currentTimeMillis() - start)); //关闭通道和流 dataOutputStream.close(); inputStream.close(); socket.close(); } }
package com.example.netty.io.zerocopy; import java.io.FileOutputStream; import java.io.IOException; import java.net.InetSocketAddress; import java.net.ServerSocket; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; /** * Description: 零拷贝 服务端 * * @Author: zhx & moon hongxu_1234@163.com * @Date: 2022-01-23 18:38 * @version: V1.0.0 */ public class NewCopyServer { public static void main(String[] args) throws IOException { //监听端口 InetSocketAddress inetSocketAddress = new InetSocketAddress(7800); //创建ServerSocketChannel ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); //获取Socket ServerSocket serverSocket = serverSocketChannel.socket(); //绑定 serverSocket.bind(inetSocketAddress); //创建Buffer ByteBuffer buffer = ByteBuffer.allocate(4096); while (true){ SocketChannel socketChannel = serverSocketChannel.accept(); //创建输出流 FileOutputStream fileOutputStream = new FileOutputStream("copy.jpg"); //获取输出流通道 FileChannel writeChannel = fileOutputStream.getChannel(); long readCount; long total = 0; while (-1!=(readCount = socketChannel.read(buffer))){ total += readCount; //切换状态 buffer.flip(); //写入文件 writeChannel.write(buffer); //清空 buffer.clear(); } writeChannel.close(); fileOutputStream.close(); System.out.println("读取字节数:" + total); } } }
package com.example.netty.io.zerocopy; import java.io.FileInputStream; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.channels.FileChannel; import java.nio.channels.SocketChannel; /** * Description: 零拷贝 客户端 * * @Author: zhx & moon hongxu_1234@163.com * @Date: 2022-01-23 18:51 * @version: V1.0.0 */ public class NewCopyClient { public static void main(String[] args) throws IOException { SocketChannel socketChannel = SocketChannel.open(); socketChannel.connect(new InetSocketAddress("127.0.0.1",7800)); //1.创建一个输出流->channel FileInputStream fileInputStream = new FileInputStream("night.jpg"); //2.获取输入流通道 FileChannel readChannel = fileInputStream.getChannel(); long start = System.currentTimeMillis(); /** * transferTo 底层为零拷贝实现 * 在linux 下一次调用 transferTo 方法就可以传输完成 * 在windows 下一次调用 transferTo 只能发送 8mb 需要分段处理 * 获取字节数 1mb = 1024kb = 1024 * 1024 byte = 1024 * 1024 * 1024 bit * 判断操作系统类型,如果为 windows 就获取字节数 fileInputStream.available() * 8mb = 1024 * 1024 byte 做循环发送即可 */ long transferCount = readChannel.transferTo(0,readChannel.size(),socketChannel); System.out.println("发送总字节数:" + transferCount + " 耗时(MS):" + (System.currentTimeMillis() - start)); readChannel.close(); socketChannel.close(); } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。