复习复习nio的api之--SocketChannel read
突然想到了netty是怎么读数据的,其实底层还是依赖jdk的nio,但是有想不起来了nio的api怎么调用的了。感觉找找过去自己写过的代码
private void read(SelectionKey key) { try { //建立写缓冲区 ByteBuffer readBuf = ByteBuffer.allocate(1024); //2 获取之前注册的socket通道对象 SocketChannel sc = (SocketChannel) key.channel(); //3 读取数据 int count = sc.read(readBuf); //4 如果没有数据 if(count == -1){ key.channel().close(); key.cancel(); return; } //5 有数据则进行读取 读取之前需要进行复位方法(把position 和limit进行复位) readBuf.flip(); //6 根据缓冲区的数据长度创建相应大小的byte数组,接收缓冲区的数据 byte[] bytes = new byte[readBuf.remaining()]; //7 接收缓冲区数据 readBuf.get(bytes); //8 打印结果 String body = new String(bytes).trim(); System.out.println("客户端已接受到服务端返回的数据: " + body); } catch (IOException e) { e.printStackTrace(); } }
就是这么简简单单的一句话,不过实现类就是操作系统底层的东西了。
abstract int read(ByteBuffer dst) 从该通道读取到给定缓冲区的字节序列。
上面的示例只是简单情况,一般都是这么写的
while (socketChannel.read(buf) > 0) {
processBuf(buf);
}
同时注意返回值有三种
1 读取的字节数,能读到会大于0
2 可能为零,说明本次epoll已经读完了
3 如果通道已达到流出端, 则为-1。read返回-1说明客户端的数据发送完毕,并且主动的close socket。所以在这种场景下,(服务器程序)你需要关闭socketChannel并且取消key,最好是退出当前函数。注意,这个时候服务端要是继续使用该socketChannel进行读操作的话,就会抛出“远程主机强迫关闭一个现有的连接”的IO异常。