码迷,mamicode.com
首页 > 其他好文 > 详细

Select、Poll、Epoll IO复用技术

时间:2020-07-08 11:38:45      阅读:66      评论:0      收藏:0      [点我收藏+]

标签:ref   libev   简单的   模型   read   语言   限制   调用   并且   

简介

  目前多进程方式实现的服务器端,一次创建多个工作子进程来给客户端提供服务,

但是创建进程会耗费大量资源,导致系统资源不足
IO复用技术就是让一个进程同时为多个客户端端提供服务

IO复用技术 之 Select、Poll、Epoll

https://baijiahao.baidu.com/s?id=1611547498841608701&wfr=spider&for=pc

select模型:

说的通俗一点就是各个客户端连接的文件描述符也就是套接字,都被放到了一个集合中,调用select函数之后会一直监视这些文件描述符中有哪些可读,如果有可读的描述符那么我们的工作进程就去读取资源。PHP 中有内置的函数来完成 select 系统调用。

函数原型:

int socket_select (array &$read ,array &$write ,array &$except ,int $tv_sec [,int $tv_usec= 0 ])

作用说明:用于确定一个或多个套接字的状态,对每一个套接字,调用者可查询它的可读性、可写性及错误状态信息

参数说明:

read: 指向一组等待可读性检查的套接字

write: 指向一组等待可写性检查的套接字

except: 指向一组等待错误检查的套接字

tv_sec: 用来设置 select() 的等待时间,秒

tv_usec: 用来设置 select() 的等待时间,微妙

这里注意一下,如果 tv_sec 设置为0,则 socket_select 立即返回,也就是非阻塞的。如果 tv_sec 设置为 null ,则 socket_select 将一直阻塞到有套接字满足条件。

下面通过代码代码来简单举例:

poll模型:

poll 和 select 的实现非常类似,本质上的区别就是存放 fd 集合的数据结构不一样。select 在一个进程内可以维持最多 1024 个连接,poll 在此基础上做了加强,可以维持任意数量的连接。

但 select 和 poll 方式有一个很大的问题就是,我们不难看出来 select 是通过轮训的方式来查找是否可读或者可写,打个比方,如果同时有100万个连接都没有断开,而只有一个客户端发送了数据,所以这里它还是需要循环这么多次,造成资源浪费。

所以后来出现了 epoll系统调用。

epoll模型:

epoll 是 select 和 poll 的增强版,epoll 同 poll 一样,文件描述符数量无限制。

epoll是基于内核的反射机制,在有活跃的 socket 时,系统会调用我们提前设置的回调函数。而 poll 和 select 都是遍历。

但是也并不是所有情况下 epoll 都比 select/poll 好,比如在如下场景:

在大多数客户端都很活跃的情况下,系统会把所有的回调函数都唤醒,所以会导致负载较高。既然要处理这么多的连接,那倒不如 select 遍历简单有效。

在 PHP 中我们可以使用 libevet 拓展来实现 epoll。

libevent 是一个用C语言写的,基于事件驱动的高性能网络库。支持多种 I/O 多路复用技术,epoll、 poll、 dev/poll、 select 和 kqueue 等。 libevent 同时为文件描述符、信号、超时设定等事件提供了监听回调。所以这种编程方式也可以说是事件编程。

先放代码体验一番:

服务端:

客户端:

先说简单的客户端,客户端的主要作用也就是像服务端发送了两句话。第一句是 hello world!,然后等待两秒之后再次发送 send again!

并且每次发送之后都将接收到服务端返回的字节数。

讲解服务端之前先了解一下关于时间循环的一些函数:

event_base_new 创建一个事件库(只需创建一次)

event_new 创建事件

event_set 为创建的事件设置要监听文件描述符fd,以及事件类型、回调函数

event_base_set 将创建的事件与事件库关联

event_add 将设置好的事件加入事件监听器

event_base_loop 开启事件循环

还有 event_set 的几个参数:

  • EV_TIMEOUT: 超时

  • EV_READ: 只要网络缓冲中还有数据,回调函数就会被触发

  • EV_WRITE: 只要塞给网络缓冲的数据被写完,回调函数就会被触发

  • EV_SIGNAL: POSIX信号量

  • EV_PERSIST: 不指定这个属性的话,回调函数被触发后事件会被删除

服务端的三个函数:

read_cb() 接受数据,发送数据

error_cb() 错误处理

accept_cb() 受理请求并且把新的文件描述符加入事件库,同时注册 read_cb 回调

整个服务端的主要流程如下:

1.创建事件库

2.设置事件回调

3.绑定事件

4.开始事件循环

5.如有符合条件的文件描述符则系统开始调用我们提前设定好的处理函数

Select、Poll、Epoll IO复用技术

标签:ref   libev   简单的   模型   read   语言   限制   调用   并且   

原文地址:https://www.cnblogs.com/coilan/p/13265975.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!