通道(Channel)
-
Channel类似于流,有些区别
- 同时进行读写,而流只能读或者只能写
- 实现异步读写数据
- 可以从缓冲读数据,也可以写数据到缓冲
-
Channel在 NIO 中是一个接口:public interface Channel extends Closeable{}
-
常用的Channel类有:FileChannel、DatagramChannel、ServerSocketChannel和SocketChannel
- ServerSocketChannel类似 ServerSocket
- SocketChannel类似Socket
-
FileChannel 用于文件的数据读写,DatagramChannel用于UDP的数据读写,ServerSocketChannel和SocketChannel 用于 TCP 的数据读写。
FileChannel类简述
FileChannel主要用来对本地文件进行I/O 操作
- public int read(ByteBufer dst),从通道读取数据并放到缓冲区中
- public int write(ByteBuffer src),把缓冲区的数据写到通道中
- public long transferFrom(ReadableByteChannel src, long position, long count),从目标通道中复制数据到当前通道
- public long transferTo(long position,long count, WritableByteChannel target),把数据从当前通道复制给目标通道
Selector(选择器)简介
- 简介:
- Selector能够检测多个注册的通道上是否有事件发生,如果有,便获取事件然后针对每个事件进行相应的处理。这样就可以只用一个单线程去管理多个通道,也就是管理多个连接和请求。
- 只有在连接/通道真正有读写事件发生时,才会进行读写,避免了多线程之间的上下文切换导致的开销
- NIOEventLoop聚合了Selector,可以同时并发处理上千个客户端连接
- 优势:
- 可以一个线程管理多个Channel处理多个请求
- 非阻塞读写,避免频繁IO导致线程挂起
- 解决了BIO的瓶颈,提高了架构的性能、弹性伸缩能力和可靠性
- Selector类是抽象类 实现了Closeable
- 相关方法:
- selector.select()//阻塞
- selector.select(1000)//阻塞 1000 毫秒,在 1000 毫秒后返回
- selector.wakeup()//唤醒 selector
- selector.selectNow()//不阻塞,立马返还
NIO非阻塞网络编程原理分析图
- 当客户端连接时,会通过 ServerSocketChannel 得到 SocketChannel
- Selector进行监听select方法,返回有事件发生的Channel的个数
- 将 SocketChannel注册到Selector上调用register(selector,int ops),一个selector上可以注册多个SocketChannel
- 注册后返回一个 SelectionKey,会和该 Selector 关联(集合)
- 进一步得到各个 SelectionKey(有事件发生)
- 在通过 SelectionKey 反向获取 SocketChannel,使用的是channel()方法
- 可以通过得到的channel,完成业务处理
(Selector、SelectionKey、ServerScoketChannel 和 SocketChannel) 关系梳理图
NIO Server和Client实现(选修)