netty是一个应用于网络通信的简单易用的java高性能网络编程框架,因此要了解netty首先要了解网络通信的原理
用户程序进行IO读写主要调用操作系统的read/write函数,用户进程调用操作系统的read是把数据从内核缓冲区复制到进程缓冲区,write系统调用是把数据冲进程缓冲区复制到内核缓冲区,应用层面的IO操作都是缓冲区的操作,实际的内核缓冲区数据到磁盘、网卡等物理设备的过程是由操作系统内核完成的;因此对于应用程序来说,socket的IO和文件的IO,其输入(Input)和输出(Output)的处理,在编程角度来说是一样的
在上面的描述中,系统调用、内核缓冲区、进程缓冲区、socket等名词值得关注
同步和异步:同步和异步是针对应用程序内核交互而言,也可理解为站在操作系统来看待程序处理过程。同步是用户进程出发IO操作并等待或轮询的去查看是否就绪,而异步是指用户进程出发IO操作后继续执行后续操作,当IO操作完成时操作系统给进程发送通知,此异步方式利用了CPU的中断功能
阻塞和非阻塞:阻塞和非阻塞是针对进程访问数据时候,也可理解为站在我们编写程序的角度看待。阻塞方式下读取或写入方法将一直等待,而非阻塞方式下读取或写入方法会立即返回一个状态值
网络IO和磁盘IO:网络IO指的是两个主机通过通信协议相互发送消息,涉及从应用程序到硬件的写入及应用程序从硬件的读出;磁盘IO是指用户进程使用内核进程读取文件的过程
一个大概的系统调用如下:
客户端发起请求:服务器主机通过网卡读取客户端的请求数据,一般所能接触到的就是IP协议,网卡调用TCP/IP协议栈程序处理,之后通知cpu将数据读取到内核缓冲区
获取请求数据:java服务器程序通过socket方式创建输入流,调用操作系统的read将内核缓冲区的数据复制到java进程缓冲区
服务器业务处理:java应用程序在jvm中执行业务代码处理客户端的请求
服务端返回数据:java程序处理完请求逻辑后构建好响应数据,然后采用write系统调用将数据从进程缓冲区复制到内核缓冲区
数据响应:操作系统将内核缓冲区的数据写入网卡,网卡通过对应的通信协议将数据包发送出去
主要的IO模型:
1.同步阻塞IO(Blocking IO),BIO
主要是指需要内核IO操作彻底完成后才返回到用户空间执行用户的操作,阻塞是指用户空间程序的执行状态,即在发生IO时cpu从用户进程切换到内核进程中去执行
2.同步非阻塞IO(Non-blocking IO),NIO
指的是用户空间的程序不需要等待内核IO操作彻底完成,可以立即返回用户空间执行用户的操作,用户进程另起一个线程向内核请求数据,拿到数据后用户进程再读取数据进行下一步处理;此NIO并非java的NIO库
3.IO多路复用(IO Multiplexing)
系统内核增加一个select函数,select函数通过绑定用户进程的fd并监视内核的数据准备情况,内核数据准备好后由select通知用户进程读取数据进行处理,这样的操作是为了避免多个用户进程调用稀缺的recvfrom线程;java中的Selector选择器和linux的epoll都是这种模型
4.信号驱动IO模型(Signal driven IO),SIGIO
用户进程进行系统调用时,内核注册一个用户进程信号并立即返回结果,用户进程继续操作,数据准备好以后内核发送一个信号给用户进程通知其读取数据
5.异步IO(Asynchronous IO),AIO
异步IO和同步IO其本质的区别是数据从内核空间复制到用户空间的过程,异步IO中用户进程向内核空间注册各种IO事件的回调函数,内核准备好数据后触发相应的事件然后主动调用用户进程去处理数据
参考:
数据从网卡到应用的过程:https://chenyongjun.vip/articles/108
socket怎么知道数据来源那个网卡:https://blog.csdn.net/weixin_39689297/article/details/111014627