复习复习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异常。

  

原文地址:https://www.cnblogs.com/juniorMa/p/14277389.html