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