前言:
记录的内容基本是之前学习Netty时候的笔记,后续还会补上几种线程模型,还有项目部分的思路(关于Netty)
1.NIO(只记录重点流程)
1.selector部分
selector里面有一系列注册好的selectionkey的集合,每一个selectionkey对应一个channel,然后去看是读还是写 还是连接的accept发生了,根据不同的事件去处理; 可以反向得到关联的channel;
select方法是执行一个阻塞的方法,在监听,没有参数的话 就是阻塞的,直到有一个关心的事件发生了就会返回; 但是select方法有一个参数是时间,在一定时间内没有观察到事件就会返回! selectNow是马上去观察,没有看到就返回
2.实践流程:
服务器端创建serverSocketChannle,并且获得serverSoctet绑定端口,进行监听
,serverSoctetChannle也要注册到selector里面去,关心的事件是accept事件! 可以只等待一秒!(其实这就是非阻塞的实现);如果观察到了事件,就获取相应的selectionkey集合,使用迭代器去遍历selectionkey,然后判断是什么事件,做相应的处理就可以了;
1.如果是连接就创建一个SoctetChannle;注意这里是虽然accept方法,但是这个时候确定是连接到了,就不用阻塞,以前的accept方法阻塞是因为不知道有没有事件到来!
- 把得到的SoctetChannle注册到selector上去,同时注册一个buffer;一个selector可以注册多个SoctetChannle;
- 注册后返回一个selectkey,和selector关联起来;
- selector就可以进行监听,利用select监听,返回管理事件发送的通道的个数。
- 一旦拿到事件以后,拿到各个有事件发生的selectkey,最后通过selectkey得到channel; 可以得到channel 完成业务处理
2.如果是读取 ,就获取对应的channel,然后获得channle对应的buffer,然后进行处理就可以了, 处理完以后一定要删除对应的selectionkey,防止重复操作
客户端方面:得到一个SoctetChannle,提供服务器端的ip和端口,然后将buffer数据写入到channle就可以了
(推荐大家看尚硅谷的Netty,讲的很好,讲师是清华大佬哦~)
2.零拷贝:
1.传统的IO
2.mmap(内存映射)
3.sendfile优化
没有真正的实现零拷贝,所谓的零拷贝并不是说完全没有拷贝,DMA拷贝还是有的,但是没有CPU拷贝
用transfer to方法去拷贝(直接从文件系统缓存到目标的channle 没有实际的拷贝,只是用了DMA拷贝,没有CPU拷贝,到了channle以后直接到对方的文件里去)
mmap实现的是 用户态和内核态的映射,不用拷贝到用户态了,少了一次拷贝次数,但是上下文次数还是一样
sendFile2.1 只是没有进入用户态,但和mmap拷贝次数是一样的
sendFile2.4 实现了真正的零拷贝,直接将数据拷贝到协议栈,很少拷贝到socket buffer里,但还是会拷贝一些数据
零拷贝是从操作系统角度来看的,内核缓冲区没有数据是重复的
3.Netty
netty:基于事件驱动的 异步的网络网络
零拷贝,支持很多协议
有了NIO为什么还要有netty?
原来的NIO比较复杂,而且NIO涉及到Reactor模式,必须对多线程比较熟悉,开发工作量比较大;还有NIO里面可能会导致Selector空轮询,导致CPU 100%;