本人为菜鸟,仅供参考
1、position、limit、capacity含义
position:记录当前读或写的位置
limit:记录读和写的末尾位置
capacity:Buffer的存储的总容量,固定不变的
0 <= position <= limit <= capacity
注意:Buffer是个抽象类,并没有实现具体的存储方式等
2、Buffer写入(客户端)
//客户端
public static void main(String[] args) throws IOException, InterruptedException {
SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 9999));
Thread.sleep(2000);
ByteBuffer buffer = ByteBuffer.allocate(1024);
buffer.clear();
String message = UUID.randomUUID().toString();
buffer.put(message.getBytes());
System.out.println(buffer.position() + " " + buffer.limit());
/**
* 必须要 flip 将 position 和 limit 重置为 0-36 不然这两个属性传给为 36 1024 服务端就读的是 36-1024 的数据
* 服务端是通过 write 的 buffer 的 position 和 limit 进行读取数据的
*/
buffer.flip();
System.out.println(buffer.position() + " " + buffer.limit());
socketChannel.write(buffer);
System.out.println("发送数据:" + message);
Thread.sleep(2000);
}
未注释buffer.flip()的结果
注释buffer.flip()后的结果
3、Buffer读取(服务端)
public static void main(String[] args) throws IOException {
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.bind(new InetSocketAddress("127.0.0.1", 9999));
serverSocketChannel.configureBlocking(false);
while (true) {
SocketChannel accept = serverSocketChannel.accept();
// 判读是否有客户端连入
if (accept != null) {
accept.configureBlocking(false);
System.out.println("客户端接入------------------------");
clients.add(accept);
}
ByteBuffer buffer = ByteBuffer.allocate(1024);
// 轮询所有客户端连接然后获取数据
for (int i = 0; i < clients.size();) {
SocketChannel client = clients.get(i);
try {
int size = client.read(buffer);
// 判断该客户端是否发了数据
if (size > 0) {
System.out.println(buffer.position() + " " + buffer.limit());
buffer.flip();
System.out.println(buffer.position() + " " + buffer.limit());
String message = new String(buffer.array(), 0, size);
System.out.println("客户端的数据:" + message);
}
buffer.clear();
i++;
} catch (Exception e) {
System.out.println(clients.size());
clients.remove(i);
System.out.println(clients.size());
}
}
}
}
客户端未注释buffer.flip()的结果
客户端注释buffer.flip()后的结果
4、结果分析
flip()是什么?
public final Buffer flip() {
limit = position;
position = 0;
mark = -1;
return this;
}
未注释
客户端flip()后,服务端获取到的buffer信息为position=0,limit=36,即客户端给服务端信息,数据在position到limit之间,而服务端在得到数据后写入自己的buffer中时position同样也会后移,所以服务端未注释第一次打印为36,1024,此时服务端数据读到了buffer中了,获取buffer中的数据时也需要flip()来重置buffer,因为这时的position其实时数据的结尾,而数据的开始应该是0
注释后
注释后客户端发给服务端的position=36,limit=1024,即服务端认为数据在postiion到limit之间,所以在服务端读取后position=988,limit=1024,所以导致打印客户端发送的数据时message=""
5、总结
所以Buffer在写入、写出后都需要flip(),也是一个容易踩的坑(花了我许多时间才发现是这个玩意儿的问题)