通常我们写一个linux的client和server如下图:
网络图
但是怎么提升性能?系统是如何快速处理网络事件?因此本文就来谈谈IO复用和模式。
第一部分:模式
我们都知道socket
分为阻塞和非阻塞,阻塞情况就是卡住流程,必须等事件发生;而非阻塞是立即返回,不管事件是否有没有准备好,需要上层代码通过EAGAIN
,EWOULDBLOCK
和EINPROGRESS
等errno返回值来判断,基于非阻塞有两种网络编程模式:Reactor和Proactor事件处理。
1、Reactor
同步IO模型一般使用Reactor,如果使用线程模式,Reactor是遇到事件就通知工作线程处理,然后主线程继续循环等待事件的发生:
reactor
(1)对于网络读写,先将socket
注册到epoll
内核事件表中;
(2)使用epoll_wait
等待句柄的读写事件;
(3)当句柄的可读可写事件发生,通知工作线程执行对应的读写动作;
(4)当工作线程处理完读写动作,如果还有后续读写,工作线程可以将句柄继续注册到epoll
内核事件表中;
(5)主线程继续用epoll_wait
等待事件发生,然后继续告知工作线程处理;
2、Proactor
在讲Proactor之前我们先说说一个例子:
...
#include
int main() {
io_context_t context;
struct iocb io[1], *p[1] = {&io[0]};
struct io_event e[1];
...
// 1. 打开要进行异步IO的文件
int fd = open("xxx", O_CREAT|O_RDWR|O_DIRECT, 0644);
if (fd