type
status
date
slug
summary
tags
category
icon
password
上一章,我们讲解了
select
I/O 多路复用技术。它通过三个不同的文件描述符集合来表示不同的 I/O 事件:可读、可写和异常。但select
有一个缺点,那就是所支持的文件描述符的个数是有限的;在 Linux 系统中,select
所支持的文件描述符的最大值默认为 1024。那有没有别的 I/O 多路复用技术可以突破文件描述符个数的限制呢?当然有,
poll
就是其中一种方式。1. poll()
和
select()
相比,poll()
和内核交互的数据结构有所变化。poll()
函数的原型如下:参数说明
fds
: fds
是一个struct pollfd
数组。表示要监视的文件描述符集合,以及应用程序对每个文件描述符感兴趣的事件。nfds
: fds
数组的长度。timeout
: 超时时间,精度为毫秒。负数表示无限期阻塞;0 表示不阻塞,立马返回。其中,
struct pollfd
结构体的定义如下:这个结构体有三个成员:
fd
是文件描述符。
events
表示应用程序感兴趣的事件类型。常见的事件类型有:POLLIN
和POLLOUT
,分别表示读事件和写事件,它们之间可以进行按位或。
revents
表示“returned events”,已发生了哪些事件。revents
里除了可以包含POLLIN
和POLLOUT
外,还可以包含POLLERR
、POLLHUP
和POLLNVAL
,表示发生了某种类型的错误。注意,POLLERR
、POLLHUP
和POLLNVAL
在events
中指定是没有效果的。(man 2 poll
)
poll()
函数有一点设计地非常好:如果我们不想对某个struct pollfd
进行检测,只要将它的fd
成员设置成负数即可。这样,内核将忽略这个结构体的events
成员,待检测完毕之后,对应的revents
的值将被设为 0。select
vs poll
使用select()
时,文件描述符的上限是由fd_set
的实现决定的,我们没办法进行修改;而在poll()
里,监视文件描述符的个数是由struct pollfd
数组的长度决定的,而数组是我们自己申请的。2. 经典案例——聊天室
接下来,我们使用
poll()
来构建一个多人聊天室服务器:- 准许多人同时进入聊天室,也允许任何人随时退出聊天室。
- 发送的消息会同时转发给聊天室的其他成员。
总结归纳
这一章,我们讲了以下内容:
poll()
——poll
是另一种 I/O 多路复用的方式,它的性能和select
相差无几。poll
和select
的区别在于:poll
没有文件描述符上限的限制。
- 最后,我们用
poll
重写了聊天室服务器的案例。希望通过这个案例,大家能熟练掌握poll()
的用法。
参考文章
- UNIX Network Programming, Volume 1: The Sockets Networking API, 3rd Edition
欢迎您在底部评论区留言,我们一起交流学习~
- 作者:Thomas He
- 链接:https://notion-next-lovat-ten.vercel.app/article/networkprogramming/7
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
相关文章