学习并写作这篇文章的初衷是项目中需要使用中国移动CMPP3.0短信网关协议实现短信发送和接受功能,其中需要基于tcp协议构建长连接,进行客户端与短信网关之间的交互。
说道tcp协议、长连接和网络编程,必须要提一下netty了。netty是一个基于java nio的,由异步事件驱动的客户端服务器网络框架,用于简单方便构建持续高可靠的网络应用,包括客户端和服务器端的协议。
netty是基于java nio实现的,对nio进行了封装,使基于netty的nio应用开发过程变得简单和易于维护。java nio,曰:java new io,又曰:java non-blocking io,是jdk 1.4之后提供的新特性。其通过引入byteBuffer缓存池的的数据结构,提高了高并发下io操作的性能。nio网上资料很多,有深到操作系统层面,有浅到api操作层面的技术文档。
通过文献阅读,我觉得nio与io的区别在于,引入bytebuffer缓存池,使io流的数据先存入缓存池,然后再通过线程池中有限的线程资源进行处理,一方便减少了线程的数量,另一方便提高了io线程的处理效率。而blocking io是同步的,每一次io操作都必须通过一个io线程进行操作,期间不能中断。
1 nio中重要基本概念
nio中有三个基本概念需要了解:
- Channels
- Buffers
- Selectors
1.1 Channels
channel是一个通道,可理解为一个双向的流。如下图所示:
数据通过channel写到buffer中,也可以从buffer中写回channel。nio中channel的实现由多个,涵盖UDP、TCP、网络io和文件io。主要channel实现:
- FileChannel 连接并处理文件读写的channel
- DatagramChannel 能收发UDP数据包的通道
- SocketChannel 连接到TCP网络套接字的通道
- ServerSocketChannel 服务器端监听TCP连接的通道,是服务器端的SocketChannel
channel之间也可以进行交互,数据可以从一个channel流入另一个channel,如图:
1.2 Buffers
顾名思义,Buffers是一个数据缓存区,数据直接通过io读写到buffer中,线程从buffer中对数据进行处理而不是直接处理数据。就像火影忍者中春野樱的百豪之术一样,可以将buffer看成一个巨大的查克拉池,数据就是查克拉。
Buffer还提供了io发送数据的基本数据类型支持。nio中Buffer主要以ByteBuffer类型出现,ByteBuffer具有一个类似队列的数据结构,其中定义了一些属性和方法,方便线程对buffer中数据的操作。主要属性有:
- position 队列游标
- capacity buffer队列的长度
- flip 控制队列 读/写 模式的翻转
- clear,compact 对队列记性清空和清理
channel具有对buffer的处理能力:
Scatter/Reads:
Gather/Writes:
1.3 Selector
Selector用于管理多个Channel,首先Channel注册到selector上,selector通过检查感兴趣的事件在注册的channels上面是否准备就绪进行channel的选择。Selector允许单线程处理多个channel,使一个单独线程易于管理多个通道。
pipe对2个线程之间单向数据连接提供支持。
SinkChannel用于从一个线程中读取数据,SourceChannel用于向另一个线程中写入数据。
2 netty
—未完待续