NIO學習筆記(4) – Scatter/Gather
分散(scatter)從 Channel 中讀取是指在讀操作時将讀取的資料寫入多個 buffer 中。是以,Channel 将從 Channel 中讀取的資料 “分散(scatter)” 到多個 Buffer 中。
聚集(gather)寫入 Channel 是指在寫操作時将多個 buffer 的資料寫入同一個 Channel,是以,Channel 将多個 Buffer 中的資料 “聚集(gather)” 後發送到 Channel。
scatter / gather 經常用于需要将傳輸的資料分開處理的場合,例如傳輸一個由消息頭和消息體組成的消息,你可能會将消息體和消息頭分散到不同的 buffer 中,這樣你可以友善的處理消息頭和消息體。
1. cattering Reads
Scattering Reads 是指資料從一個 channel 讀取到多個 buffer 中。如下圖描述:
2.Gathering Writes
Gathering Writes 是指資料從多個 buffer 寫入到同一個 channel。如下圖描述
代碼示例:
public class NioTest11 {
public static void main(String[] args) throws IOException {
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
// 綁定8899端口
InetSocketAddress address = new InetSocketAddress(8899);
// 啟動伺服器
serverSocketChannel.socket().bind(address);
int messageeLength = 2 + 3 + 4;
ByteBuffer[] byteBuffers = new ByteBuffer[3];
byteBuffers[0] = ByteBuffer.allocate(2);
byteBuffers[1] = ByteBuffer.allocate(3);
byteBuffers[2] = ByteBuffer.allocate(4);
// 等待用戶端連接配接
SocketChannel socketChannel = serverSocketChannel.accept();
while (true) {
int byteRead = 0;
while (byteRead < messageeLength) {
// 這裡是直接讀取的byteBuffers
final long r = socketChannel.read(byteBuffers);
byteRead += r;
System.out.println("byteRead :" + byteRead);
Arrays.asList(byteBuffers).stream().map(buffer -> "position:" + buffer.position() + ",limit" + buffer.limit())
.forEach(System.out::println);
}
Arrays.asList(byteBuffers).forEach(byteBuffer -> byteBuffer.flip());
int byteWritten = 0;
// 等讀的數量到達messageeLength長度才發送給用戶端
while (byteWritten < messageeLength) {
// 這裡是直接寫的byteBuffers
long w = socketChannel.write(byteBuffers);
byteWritten += w;
}
Arrays.asList(byteBuffers).forEach(byteBuffer -> byteBuffer.clear());
System.out.println("byteRead:" + byteRead + ",byteWritten" + byteWritten + ",messageeLength" + messageeLength);
}
}
}
驗證代碼:
>./nc localhost 8899 // 表示連接配接到本地8899端口,這裡使用的是ServerSocketChannel,是以為長連接配接
>88888888 // 輸入八位數 + 回車,剛剛死九尾,是以說這裡服務端會傳回一個88888888