编程技术分享平台

网站首页 > 技术教程 正文

网络I/O模型(网络io模型有哪几种)

xnh888 2024-10-28 20:38:26 技术教程 33 ℃ 0 评论

实现层面的网络I/O模型(“Linux 系统)

第一种模型:同步阻塞I/O。

Linux系统的read和write函数,在调用的时候会被阻塞,直到数据读取完成,或者写入成功。

第二种模型:同步非阻塞I/O。和同步阻塞I/O的API是一样的,只是打开fd的时候带有O_NONBLOCK参数。于是,当调用read和write函数的时候,如果没有准备好数据,会理解返回,不会阻塞,然后让应用程序不断地去轮询。

第三种模型:I/O多路复用(IO Multiplexing)。

前面两种I/O都只能用于简单的客户端开发。但对于服务器程序来说,需要处理很多的fd (连接数可以达几十万甚至百万)。

如果使用同步阻塞I/O,要处理这么多的fd需要开非常多的线程,每个线程处理一个 fd;

如果用同步非阻塞 I/O,要应用程序轮询这么大规模的 fd。

这两种办法都不行,所以就有了I/O多路复用。

在Linux系统中,有三种I/O多路复用的办法:select、poll、epoll,它们的原理有一定差异。


该函数是阻塞调用,一次性把所有的 fd 传进去,当有 fd 可读或者可写之后,该函数会返回,返回结果也在这个函数的参数里面,告知应用程序哪些fd上面可读或者可写,然后下一步应用程序调用read和write函数进行数据读写。

I/O多路复用是现在Linux系统上最成熟的网络I/O模型,在三种方式中,epoll的效率最高,所以目前主流的网络模型都是epoll。

第四种模型:异步I/O。Windows系统的IOCP,这是一种真正意义上的异步I/O。

异步I/O,是指读写都是由操作系统完成的,然后通过回调函数或者某种其他通信机制通知应用程序。

C++中的asio网络库。asio是一个跨平台的C++网络库,也是boost的一部分,在Linux系统上封装的是epoll,在Windows系统上封装的是IOCP。asio的接口是完全异步的


async_read/async_write函数传进去的参数主要是三个:·

socket.· 应用程序的buffer· 回调函数。

chat_session 这个类的两个成员函数handle_read_header/handle_write。应用程序调用了这两个函数后都会立即返回,由asio库内部进行I/O读写。读写完成后通过传入的回调函数通知应用程序,读写已经完成。

asio 是一个上层框架层的“异步 I/O”,或者说是模拟出来的“异步I/O”,在 Linux系统上还是由epoll实现的。

“异步”,就是读写由底层完成(操作系统或者框架),读写完成之后,以某种方式通知应用程序。

Linux系统异步I/O的实现是aio。但由于aio并不成熟,所以现在主要还是用epoll。

阻塞与非阻塞


(1)阻塞和非阻塞是从函数调用角度来说的,而同步和异步是从“读写是谁完成的”角度来说的。

阻塞:如果读写没有就绪或者读写没有完成,则该函数一直等待。

非阻塞:函数立即返回,然后让应用程序轮询。

同步:读写由应用程序完成。

异步:读写由操作系统完成,完成之后,回调或者事件通知应用程序。

(2)按照这个定义可以知道,异步I/O一定是非阻塞I/O,不存在既是异步I/O,又是阻塞的;同步I/O可能是阻塞的,也可能是非阻塞的。

归类后共有三种:同步阻塞I/O、同步非阻塞I/O、异步I/O。

(3)I/O多路复用(select、poll、epoll)都是同步I/O,因为read和write函数操作都是应用程序完成的,同时也是阻塞I/O,因为select、read、write的调用都是阻塞的。

事件驱动

Nginx的“事件驱动”,是Nginx封装的一个逻辑概念,在操作系统层面是基于epoll或者select来实现的。

当讲网络 I/O 模型的时候,一定要注意讲的是操作系统层面的 I/O 模型,还是上层的网络框架封装出来的I/O模型(比如asio,又比如Java的NIO,在Linux平台上,底层也是基于epoll)。

对于“异步I/O”一词,在操作系统的语境和在上层应用的语境中,往往指代不一样。

在操作系统的语境里,异步I/O是指IOCP或者aio这种真正的异步,epoll不被认为是异步I/O;但在上层应用的语境里,异步I/O往往指的是JavaJDK或网络框架(Netty)封装出来的概念,底层实现可能是epoll,也可能是真正的异步I/O。

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表