BIO
阻塞等待连接/数据,读写都阻塞、耗带宽和资源,每个请求过来开一个线程阻塞
NIO
- 非阻塞IO,可能等的时间太久响应延迟大会重试-多路复用,通道buffer多路复用、监听事件
NIO多路复用:便捷的通知机制,程序注册一组socket文件描述符给OS,表示“我要监视这些fd是否有IO事件发生,有了就告诉程序处理”
换行符
- 消息头声明长度
- 固定报文长度补齐空位
AIO/NIO2(异步IO)
序列化
I/O模型
前置知识
创建进程分配空间
低地址位:用户空间,高地址位:内核空间
虚拟内存
通过MMU维护的页表转成真正内存
Linux 4K内存页
阻塞的本质:将task_struct移出运行队列,添加到等待队列,在内核注册回调事件,并将进程状态修改,重新出发CPU调度让渡。当事件触发(数据拷贝到内核中准备好了),触发硬件中断,内核调用回调函数唤醒进程重新加入运行队列,修改状态(过程中可能包含网卡拷贝到内核,内核向用户空间堆上拷贝数据,java涉及堆和非堆更复杂)
网络分为应用层(java)->Socket层->协议层->网络层
IO底层2大步骤:
- 数据准备阶段:用户线程等待内核将数据从网卡拷贝到内核空间
- 数据拷贝阶段:内核将数据从内核空间拷贝到用户空间(应用进程缓冲区)

各种I/O模型核心解决问题是内存和外部IO设备的速度差异问题
I/O模型阻塞点考虑的是数据准备阶段
等着拷完就是阻塞,立即返回状态就是非阻塞
I/O模型同步异步考虑的是数据拷贝阶段
内核主动发起(拷到用户空间后通知)——异步,应用程序触发(询问)——同步
多路复用——同步

Socket不同的计算机节点之间通信的端点(Endpoint)的抽象,linux是一个文件,通信就相当于往两个文件中读写
ServerSocket->调用C创建Socket->bind端口->listen端口->循环accept()三次握手
select 轮询O(n),数组一般1024个
poll 改进不大,65535实际无上限
epoll(eventpoll(wq等待队列,rdlist双向链表存储就绪socket的epitem,rbr红黑树存储监视socket的epitem))实现多路复用IO,65535实际无上限
三大方法:epoll_create/epoll_ctl/epoll_wait(LT/ET->事件就绪队列)
ET边沿触发/LT水平触发:epoll支持ET,事件通知方式不同,LT持续通知直到处理事件完毕,ET只通知一次,不管事件是否处理完毕,ET使得就绪队列上的新的就绪事件能被快速处理,避免共享 “epoll fd” 场景下,发生类似惊群问题
selector 多路复用选择器 selecor.select() handler
单Reactor模型
线程池Reactor模型
多(主从)Reactor模型——Tomcat
全连接
半连接
