Java NIO 网络编程初探

Java NIO 网络编程初探

1. Java NIO

Java 1.4 版本添加了一个新的IO API,称为NIO(New IO)。NIO拥有所有IO的功能,但是操作方法却完全不一样。NIO支持面向缓冲区的、基于通道的IO操作。能够更加高效的进行IO操作。NIO同样拥有文件读写,网络通信等IO操作,今天我们来看看NIO中的TCP网络通信的使用方法。

2. Java NIO 三大核心

Java NIO 有三大核心要素:Channel、Buffer和Selector。Java IO 的操作都是基于输入输出流的,而NIO则是基于Channel和Buffer的,数据先被读取到Buffer中,然后再进行处理。Selector作为NIO的辅助工具,能够使NIO的操作更加高效。

2.1 Buffer

NIO提供了多种Buffer,包括对应基本数据类型的ByteBuffer、CharBuffer、ShortBuffer、IntBuffer、LongBuffer、FloatBuffer和DoubleBuffer。
Buffer拥有四种属性:

  1. 容量(Capacity):缓冲区能够容纳的数据元素的最大数量。这一个容量在缓冲区创建时被设定,并且永远不能改变。
  2. 上界(Limit):缓冲区的第一个不能被读或写的元素。或者说,缓冲区中现存元素的计数。
  3. 位置(Position):下一个要被读或写的元素的索引。位置会自动由相应的 get( )和 put( )函数更新。
  4. 标记(Mark):下一个要被读或写的元素的索引。位置会自动由相应的 get( )和 put( )函数更新。
常用的Buffer方法有:
    1. 获取方法
        static XXXBuffer allocate(int capacity);
    2. 操作方法
        flip(): limit设为position的位置,position设为0,读写指针又移动到了开始的位置,调用flip()后,buffer为输出数据做好了准备。
        rewind():将 position 重置为 0 ,一般用于重复读。
        clear() :position 变成 0 , limit 变成 capacity (清空 buffer ,准备再次被写入) 。
        compact(): 将未读取的数据拷贝到 buffer 的头部位。
        mark(): reset():mark 可以标记一个位置, reset 可以重置到该位置。
        put(),get() 放入,取出数据, 分为相对(Relative)和绝对(Absolute)。

2.2 Channel

Channel用于和Buffer交互,Channel能将数据的读写映射到Buffer,能够在两个实体中有效的传输数据,Channel是数据交互的通道,而Buffer则是通道的两个端点。通过这种方式,能够极大地利用操作系统的IO能力。

Java NIO 中的通道分为四种:

  1. FileChannel:用于读取、写入、映射和操作文件的通道。(用于本地文件操作)
  2. DatagramChannel:通过UDP 读写网络中的数据通道。
  3. SocketChannel:通过TCP 读写网络中的数据。
  4. ServerSocketChannel:可以监听新进来的TCP 连接,对每一个新进来的连接都会创建一个SocketChannel。
常用的Channel方法:
    1. 获取方法
        可以直接调用通道类提供的静态方法open来获取通道的实例
        也可以通过IO流对象调用getChannel()方法来获取Channel实例

    2. 操作方法
        Channel通常是配合Buffer使用的,可以将Channel映射到Buffer中
        也可以直接调用write(Buffer buf)和read(Buffer buf)

2.3 Selector

selector使用单线程处理多个channel,当应用打开了多个channel且每个channel的吞吐量不是很大时,使用channel就比较方便。使用selector分如下的几步:参考文章

  1. 创建:使用Selector selector = Selector.open()
  2. 将channel注册到selector:channel.register(selector, **),该方法可返回一个SelectorKey,代表该channel在selector中的”代号”。与selector一起使用时,channel一定处于非阻塞模式下。所以需要提前设置channel.configureBlocking(false)。
  3. 使用selector几个select的重载方法测试通道有多少已经准备好了:
    • int select()阻塞到至少有一个对象在通道上准备好了。
    • int select(long timeout)最长会阻塞timeout毫秒
    • int selectNow()不会阻塞,不管什么情况会直接返回,如果自上次调用选择操作以来,没有就绪的通道则直接返回0。
  4. 调用select方法之后,如果有返回值,则说明已经有selector就绪了。此时可以通过selectedKey来选择已选择键集中就绪的通道。使用Set selectedKey = selector.selectedKeys();,之后在得到的SelectionKey的Set中可以通过SelectionKey提供的方法来操作channel。得到Channel的基本方法为selectionKey.channel() 。

3. Java NIO TCP网络通信

3.1 客户端实现

在这里插入图片描述

3.2 服务端实现

在这里插入图片描述

发布了34 篇原创文章 · 获赞 25 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/m0_37771142/article/details/104722044