1.Netty编程-NIO基础

  Java NIO (New IO) 是一个替代接口(从Java 1.4开始),相对于Java传统IO接口和网络接口而言。NIO处理IO的方式和传统IO会有很大区别。标准的IO基于字节流和字符流进行操作的,而NIO是基于通道(Channel)和缓冲区(Buffer)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中。NIO可以理解为非阻塞IO,传统的IO的read和write只能阻塞执行,线程在读写IO期间不能干其他事情,比如调用socket.read()时,如果服务器一直没有数据传输过来,线程就一直阻塞,而NIO中可以配置socket为非阻塞模式。NIO引入了选择器的概念,选择器用于监听多个通道的事件(比如:连接打开,数据到达)。因此,单个的线程可以监听多个数据通道。引用链接

1.NIO三大组件

1.1 channel

  通道表示打开到 IO 设备(例如:文件、套接字)的连接。若需要使用 NIO 系统,需要获取用于连接 IO 设备的通道以及用于容纳数据的缓冲区。然后操作缓冲区,对数据进行处理。 Channel相比IO中的Stream更加高效,可以异步双向传输,但是必须和buffer一起使用。

1.FileChannel,读写文件中的数据。
2.SocketChannel,通过TCP读写网络中的数据。
3.ServerSockectChannel,监听新进来的TCP连接,像Web服务器那样。对每一个新进来的连接都会创建一个SocketChannel。
4.DatagramChannel,通过UDP读写网络中的数据

1.2 buffer

  Buffer 是一个对象, 它包含一些要写入或者刚读出的数据。 在 NIO 中加入 Buffer 对象,体现了新库与原 I/O 的一个重要区别。在面向流的 I/O 中,您将数据直接写入或者将数据直接读到 Stream 对象中。在 NIO 库中,所有数据都是用缓冲区处理的。在读取数据时,它是直接读到缓冲区中的。在写入数据时,它是写入到缓冲区中的。任何时候访问 NIO 中的数据,您都是将它放到缓冲区中。缓冲区实质上是一个数组。通常它是一个字节数组,但是也可以使用其他种类的数组。但是一个缓冲区不 仅仅 是一个数组。缓冲区提供了对数据的结构化访问,而且还可以跟踪系统的读/写进程。

NIO里关键的Buffer实现:

ByteBuffer
CharBuffer
DoubleBuffer
FloatBuffer
IntBuffer
LongBuffer
ShortBuffer

1.3 selector

  selector的作用就是配合一个线程来管理多个channel,获取这些channel上发生的事件,这些channel工作在非阻塞模式下,不会让线程吊死在一个channel上。适合连接数特别多,但流量低的场景(low traffic)。
在这里插入图片描述

2.bytebuffer

2.1 bytebuffer使用

1.向buffer 写入数据,例如调用channel.read(buffer)
2.调用flip()切换至读模式
3.从buffer读取数据,例如调用buffer.get()
4.调用clear()或compact()切换至写模式
5.重复1~4步骤

  如果调用的是clear()方法,position将被设回0,limit被设置成 capacity的值。换句话说,Buffer 被清空了。Buffer中的数据并未清除,只是这些标记告诉我们可以从哪里开始往Buffer里写数据。
  compact()方法将所有未读的数据拷贝到Buffer起始处。然后将position设到最后一个未读元素正后面。limit属性依然像clear()方法一样,设置成capacity。现在Buffer准备好写数据了,但是不会覆盖未读的数据。引用链接

2.2 bytebuffer参数

capacity:容量
position:读写指针
limit:读写限制

写模式下,limit位置为最大容量。读模式下,limit为写入的字符数。
其实准确的说,bytebuffer没有读写模式之说,只是调用flip()和clear()方法移动了position和limit指针的位置,以达到读写的目的。

2.3 字符串和bytebuffer互相转换

字符串转为bytebuffer:
//1
ByteBuffer buffer = ByteBuffer.allocate(16);
buffer.put("hello".getBytes());
//2
ByteBuffer buffer2 = StandardCharsets.UTF_8.encode( str: "hello");
//3
ByteBuffer buffer3 = ByteBuffer.wrap( "hello".getBytes());
bytebuffer转为字符串:
string str1 = standardCharsets.UTF_8.decode(buffer2).toString();

3.selector

  Selector(选择器)是 Java NIO 中能够检测到一到多个 NIO 通道,并能够知道通道是否为读写事件做好准备。这样,一个单独的线程可以管理多个 Channel,从而管理多个网络连接。仅用单个线程来处理多个 Channel 的好处是,只需要更少的线程来处理通道。

3.1 selector使用

1.创建selector。
2.为channel注册selector,使用selector时,channel必须处于非阻塞模式。在注册selector时,还需要指明selector监听channel时对什么时间感兴趣。selector可以监听以下四种事件:

Read - 可读事件
Write - 可写事件
Connect - 用于客户端,连接建立后出发
Accept - 用于服务端,有连接请求时出发

3.调用select()方法,没有事件发生时,线程会阻塞,有事件发生时线程才会运行。
4.通过selectedKeys()返回的集合,遍历有事件发生的channel,处理事件。
  需要注意的是,在处理完事件后,要使用remove方法移除set中已处理过事件的channel。因为在下一次迭代中继续使用这个channel会报错。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值