1.NIO编程
- Non-Blocking I/O
- 提供非阻塞通讯等方式
- 避免同步I/O通讯效率过低
- 一个线程可以管理多个连接
- 减少线程多的压力
主要类
- Buffer 缓存区
- Channel 通道
- Selector多路选择器
Buffer
- Buffer 缓冲区,一个可以读写的内存区域
- ByteBuffer, CharBuffer, DoubleBuffer, IntBuffer, LongBuffer, ShortBuffer (StringBuffer 不是Buffer缓冲区)
- 四个主要属性
- capacity 容量
- position 读写位置
- limit 界限
- mark 标记,用于重复一个读/写操作
- 使用Buffer读写数据一般遵循以下四个步骤:
- 写入数据到Buffer
- 调用flip()方法
- 从Buffer中读取数据
- 调用clear()方法或者compact()方法
- Buffer的分配
- allocate方法
1
ByteBuffer buf = ByteBuffer.allocate(48);
- 向Buffer中写数据
- 从Channel写到Buffer
1
int bytesRead = inChannel.read(buf);
- 通过Buffer的put()方法写入Buffer
1
buf.put(127);
- flip()方法
- flip方法将Buffer从写模式切换到读模式
- 调用flip()方法会将position设回0,并将limit设置成之前position的值
- 从Buffer中读数据
- 从Buffer读取数据到Channel
1
int bytesWritten = inChannel.write(buf);
- 使用get()方法从Buffer中读取数据
1
byte aByte = buf.get();
- clear()与compact()方法
- clear()
- position将被设回0,limit被设置成 capacity的值
- Buffer 被清空了,但Buffer中的数据并未清除,只是这些标记告诉我们可以从哪里开始往Buffer里写数据
- compact()
- 将所有未读的数据拷贝到Buffer起始处,然后将position设到最后一个未读元素正后面
- limit属性依然像clear()方法一样,设置成capacity
- 不会覆盖未读的数据
- clear()
Channel
- 全双工的,支持读/写(而Stream流是单向的)
- 支持异步读写
- 和Buffer配合,提高效率
- ServerSocketChannel 服务器TCP Socket 接入通道,接收客户端
- SocketChannel TCP Socket通道,可支持阻塞/非阻塞通讯
- DatagramChannel UDP 通道
- FileChannel 文件通道
SocketChannel
- 打开SocketChannel
1 | SocketChannel socketChannel = SocketChannel.open(); |
- 关闭SocketChannel
- close()
1
socketChannel.close();
- **读取SocketChannel **
- read()
1
2ByteBuffer buf = ByteBuffer.allocate(48);
int bytesRead = socketChannel.read(buf); - 写入SocketChannel
- write()
1
2
3
4
5
6
7
8String newData = "New String to write to file...";
ByteBuffer buf = ByteBuffer.allocate(48);
buf.clear();
buf.put(newData.getBytes());
buf.flip();
while(buf.hasRemaining()) {
channel.write(buf);
}
Selector
- 每隔一段时间,不断轮询注册在其上的Channel
- 如果有一个Channel有接入、读、写操作,就会被轮询出来
- 根据SelectionKey可以获取相应的Channel,进行后续IO操作
- 避免过多的线程
- SelectionKey四种类型
- OP_CONNECT (连接就绪 某个Channel成功连接到另一个服务器)
- OP_ACCEPT (接收就绪 一个ServerSocketChannel准备好接收新进入的连接)
- OP_READ (读就绪 有数据可读的通道)
- OP_WRITE (写就绪 等待写数据的通道)
- Selector的创建
- Selector.open()方法
1
Selector selector = Selector.open();
- 向Selector注册通道
- SelectableChannel.register()方法
1
2channel.configureBlocking(false);
SelectionKey key = channel.register(selector,Selectionkey.OP_READ); - 通过Selector选择通道
- 一旦向Selector注册了一或多个通道,就可以调用几个重载的select()方法。这些方法返回你所感兴趣的事件(如连接、接受、读或写)已经准备就绪的那些通道
- select() 阻塞到至少有一个通道在你注册的事件上就绪了
- select(long timeout) 最长会阻塞timeout毫秒(参数)
- selectNow() 不会阻塞,不管什么通道就绪都立刻返回
- 访问已选择键集
- 一旦调用了select()方法,并且返回值表明有一个或更多个通道就绪了,然后可以通过调用selector的selectedKeys()方法,访问“已选择键集(selected key set)
- selectedKeys()
1
2Set selectedKeys = selector.selectedKeys();
NIO结构
graph LR p[Server]--c---s[Server
Socket
Channel] s--c---sr[Selector] sr--c---b01[Buffer] sr--c---b02[Buffer] sr--c---b03[Buffer] b01--c---s01[Selector] b02--c---s02[Selector] b03--c---s03[Selector] s01--c---c1[Client1] s02--c---c2[Client2] s03--c---c3[Client3]
1 | //Server |
2.AIO编程
- Asynchronous I/O, 异步I/O
- JDK 1.7引入,主要在java.nio包中
- 异步I/O,采用回调方法进行处理读写操作
主要类
- AsynchronousServerSocketChannel 服务器接受请求通道
- bind 绑定在某一个端口 accept 接受客户端请求
- AsynchronousSocketChannel Socket通讯通道
- read 读数据 write 写数据
- CompletionHandler 异步处理类
- completed 操作完成后异步调用方法 failed 操作失败后异步调用方法
1 | //服务器通道建立 |
三种I/O的区别
BIO | NIO | AIO | |
---|---|---|---|
阻塞方式 | 阻塞 | 非阻塞 | 非阻塞 |
同步方式 | 同步 | 同步 | 异步 |
编程难度 | 简单 | 较难 | 困难 |
客户机/服务器线程对比 | 1:1 | N:1 | N:1 |
性能 | 低 | 高 | 高 |
3.Netty编程
关键技术
- 通道 Channel
- ServerSocketChannel/NioServerSocketChannel/…
- SocketChannel/NioSocketChannel
- 事件 EventLoop
- 为每个通道定义一个EventLoop,处理所有的I/O事件
- EventLoop注册事件
- EventLoop将事件派发给ChannelHandler
- EventLoop安排进一步操作
- 事件
- 事件按照数据流向进行分类
- 入站事件:连接激活/数据读取/……
- 出站事件:打开到远程连接/写数据/……
- 事件处理 ChannelHandler
- Channel通道发生数据或状态改变
- EventLoop会将事件分类,并调用ChannelHandler的回调函数
- 程序员需要实现ChannelHandler内的回调函数
- ChannelInboundHandler/ChannelOutboundHandler
- ChannelHandler工作模式:责任链
- 责任链模式
- 将请求的接收者连成一条链
- 在链上传递请求,直到有一个接收者处理该请求
- 避免请求者和接收者的耦合
- ChannelHandler可以有多个,依次进行调用
- ChannelPipeline作为容器,承载多个ChannelHandler
- 责任链模式
- ByteBuf
- 强大的字节容器,提供丰富API进行操作
1 | //from BiliBili |
4.邮件基础知识
主要协议(发送端口25, 接收端口110)
- 发送, SMTP, Simple Mail Transfer Protocol
- 接收, Pop3, Post Office Protocol 3, (POP)
- 接收, IMAP, Internet Message Access Protocol, IMAP4
- 摘要浏览
- 选择下载附件
- 多文件夹
- 网络硬盘
5.Mail编程
邮件服务器支持
- 需要在邮件服务内设置,可以查看相关邮件帮助
- 需要知道pop服务器和smtp服务器信息
javax.mail 包和javax.mail.internet 包
关键类
- Session: 邮件会话 和HttpSession不同
- Store: 邮件存储空间
- Folder: 邮件文件夹
- Message: 电子邮件
- Address: 邮件地址
- Transport: 发送协议类
1 | //Receive |