Java NIO 网络编程初探

Ivy ·
更新时间:2024-11-01
· 781 次阅读

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拥有四种属性:

容量(Capacity):缓冲区能够容纳的数据元素的最大数量。这一个容量在缓冲区创建时被设定,并且永远不能改变。 上界(Limit):缓冲区的第一个不能被读或写的元素。或者说,缓冲区中现存元素的计数。 位置(Position):下一个要被读或写的元素的索引。位置会自动由相应的 get( )和 put( )函数更新。 标记(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 中的通道分为四种:

FileChannel:用于读取、写入、映射和操作文件的通道。(用于本地文件操作) DatagramChannel:通过UDP 读写网络中的数据通道。 SocketChannel:通过TCP 读写网络中的数据。 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分如下的几步:参考文章

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

在这里插入图片描述

3.2 服务端实现

在这里插入图片描述


作者:留恋逝去的残梦



网络编程 nio JAVA

需要 登录 后方可回复, 如果你还没有账号请 注册新账号