使用傳統的IO 方法傳遞一個大檔案
使用NIO 零拷貝方式傳遞(transferTo)一個大檔案
看看兩種傳遞方式耗時時間分別是多少
服務端程式碼
public class OldServer {
public static void main(String[] args) {
try {
ServerSocket serverSocket = new ServerSocket(1212);
System.out.println("服務端啟動已啟動......");
while (true) {
// 等待連線
Socket socket = serverSocket.accept();
new Thread(new Runnable() {
@Override
public void run() {
// 接收訊息
try (InputStream inputStream = socket.getInputStream()){
byte[] result = new byte[1024];
while (true) {
int read = inputStream.read(result);
if (read == -1) {
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
客戶端程式碼
public class OldClient {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("localhost", 1212);
OutputStream outputStream = socket.getOutputStream();
// 檔案大小為300MB
File file = new File("D:\\電子書\\深入理解Apache Dubbo與實戰.pdf");
FileInputStream fileInputStream = new FileInputStream(file);
byte[] buffer = new byte[(int) file.length()];
long total = 0;
long startTime = System.currentTimeMillis();
while (true) {
long readCount = fileInputStream.read(buffer);
if (readCount == -1) {
break;
}
total += readCount;
outputStream.write(buffer);
}
outputStream.flush();
System.out.println("傳送總位元組數: " + total + ", 耗時: " + (System.currentTimeMillis() - startTime));
fileInputStream.close();
socket.close();
}
}
服務端程式碼
public class NewIOServer {
public static void main(String[] args) throws Exception {
InetSocketAddress address = new InetSocketAddress(1313);
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
ServerSocket serverSocket = serverSocketChannel.socket();
serverSocket.bind(address);
System.out.println("服務端啟動已啟動......");
//建立buffer
ByteBuffer byteBuffer = ByteBuffer.allocate(4096);
while (true) {
SocketChannel socketChannel = serverSocketChannel.accept();
int readcount = 0;
while (-1 != readcount) {
try {
readcount = socketChannel.read(byteBuffer);
}catch (Exception ex) {
// ex.printStackTrace();
break;
}
//
byteBuffer.rewind(); //倒帶 position = 0 mark 作廢
}
}
}
}
客戶端程式碼
public class NewIOClient {
public static void main(String[] args) throws Exception {
SocketChannel socketChannel = SocketChannel.open();
socketChannel.connect(new InetSocketAddress("localhost", 1313));
// 檔案大小為300MB
String filename = "D:\\電子書\\深入理解Apache Dubbo與實戰.pdf";
//得到一個檔案channel
FileChannel fileChannel = new FileInputStream(filename).getChannel();
//準備傳送
long startTime = System.currentTimeMillis();
// 在linux下,一次transferTo 就可以完成傳輸
//transferTo 底層使用到零拷貝
// long transferCount = fileChannel.transferTo(0, fileChannel.size(), socketChannel);
//在windows下,一次ransferTo 只能傳送8m , 就需要分段傳輸檔案
long total = 0;
long position = 0; // 讀取位置
while (true) {
long transferCount = fileChannel.transferTo(position, fileChannel.size(), socketChannel);
if (transferCount > 0) {
position = position + transferCount;
total = total + transferCount;
} else {
break;
}
}
System.out.println("傳送的總的位元組數 =" + total + " 耗時:" + (System.currentTimeMillis() - startTime));
//關閉
fileChannel.close();
}
}
本作品採用《CC 協議》,轉載必須註明作者和本文連結