这个例子,在客户端通过transferTo方法,直接将文件通过DMA拷贝到socketChannel,服务端将收到的数据进行打印到控制台
客户端
package org.scaventz.zerocopy; import java.io.FileInputStream; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.channels.FileChannel; import java.nio.channels.SocketChannel; public class NewIoClient { public static void main(String[] args) throws IOException { SocketChannel socketChannel = SocketChannel.open(); socketChannel.connect(new InetSocketAddress("localhost", 7001)); String filename = "d:/test.txt"; // 得到一个文件的channel FileChannel fileChannel = new FileInputStream(filename).getChannel(); // 准备发送 long startTime = System.currentTimeMillis(); // 在linux下一个transferTo方法就可以完成传输 // 在windows下一次调用transferTo只能发送8M文件,就需要分段传输文件,而且要注意传输时的位置 // transferTo底层使用到了零拷贝 long transferCount = fileChannel.transferTo(0, 8 * 1024 * 1024, socketChannel); System.out.println("发送的总的字节数 = " + transferCount + " 耗时 = " + (System.currentTimeMillis() - startTime)); fileChannel.close(); } }
服务端
package org.scaventz.zerocopy; import java.io.IOException; import java.net.InetSocketAddress; import java.net.ServerSocket; import java.nio.ByteBuffer; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; /** * @Description */ public class NewIoServer { public static void main(String[] args) throws IOException { InetSocketAddress address = new InetSocketAddress(7001); ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); ServerSocket serverSocket = serverSocketChannel.socket(); serverSocket.bind(address); // 创建buffer ByteBuffer byteBuffer = ByteBuffer.allocate(4096); while (true) { SocketChannel socketChannel = serverSocketChannel.accept(); int count = 0; while (count != -1) { try { // 将数据读入 byteBuffer count = socketChannel.read(byteBuffer); System.out.println(new String(byteBuffer.array())); } catch (Exception e) { e.printStackTrace(); break; } byteBuffer.rewind(); // 倒带 position = 0, mark=-1 作废 } } } }