06 网络2
06 网络2
参考资料:9.2 I/O 多路复用:select/poll/epoll | 小林coding (xiaolincoding.com)
select
select 允许程序同时监视多个文件描述符(通常是套接字描述符),以确定是否有任何文件描述符准备好读取、写入或有错误。它是一种在单个线程中处理多个 I/O 操作的机制。
函数原型
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); |
参数
-
nfds: 需要监视的最大文件描述符加1。例如,如果你监视的最大文件描述符是 5,则nfds应该是 6。 -
readfds: 指向一个集合,包含需要监视读取状态的文件描述符。 -
writefds: 指向一个集合,包含需要监视写入状态的文件描述符。 -
exceptfds: 指向一个集合,包含需要监视异常条件的文件描述符。 -
timeout: 指向一个timeval结构,指定select调用的超时时间。如果为 NULL,则select会一直阻塞直到有文件描述符准备好。
返回值
-
成功时,返回准备好的文件描述符的数量。
-
错误时,返回-1。
fd_set 结构体
fd_set 是一个用于 select 函数的特定数据结构,它能够存储一组非负的文件描述符(通常是套接字)。这个结构体在 <sys/select.h> 头文件中定义,但它的具体实现是依赖于平台的。
-
FD_ZERO(fd_set *set): 这个宏将fd_set初始化为空集合,即没有任何文件描述符。 -
FD_SET(int fd, fd_set *set): 这个宏将文件描述符fd添加到fd_set集合中。 -
FD_CLR(int fd, fd_set *set): 这个宏从fd_set集合中移除文件描述符fd。 -
FD_ISSET(int fd, fd_set *set): 这个宏检查文件描述符fd是否在fd_set集合中。
struct timeval 结构体
timeval 结构体用于指定时间间隔,它在 <sys/time.h> 头文件中定义。select 函数使用它来设置操作的超时时间。
-
struct timeval { long tv_sec; // 秒 long tv_usec; // 微秒 };
服务器示例
|
poll
poll 是一种比 select 更灵活的 I/O 多路复用技术,它允许程序同时监视多个文件描述符,以确定是否有任何文件描述符准备好进行读取、写入或出现错误。与 select 不同,poll 没有最大文件描述符数量的限制,并且可以监视更多的事件类型。
函数原型
int poll(struct pollfd *fds, nfds_t nfds, int timeout); |
参数
-
fds: 指向一个pollfd结构体数组,每个结构体代表一个要监视的文件描述符。 -
nfds: 数组中的结构体数量。 -
timeout: 指定poll调用的超时时间(毫秒)。如果为 -1,则poll会一直阻塞直到有文件描述符准备好。
返回值
-
成功时,返回准备好的文件描述符的数量。
-
错误时,返回 -1。
struct pollfd 结构体
pollfd 结构体用于 poll 函数,它定义了要监视的文件描述符和相关的事件。
struct pollfd { |
-
events字段可以是以下宏的组合:POLLIN: 文件描述符可读。POLLOUT: 文件描述符可写。POLLERR: 出现错误。POLLHUP: 对端关闭连接。
-
revents字段在poll返回后,会设置为以下宏的组合之一:POLLIN: 有数据可读。POLLOUT: 可以写入数据。POLLERR: 检测到错误。POLLHUP: 对端关闭连接。
服务器示例
以下是一个使用 poll 的简单 echo 服务器示例:
|
epoll
了解您的需求,我会给出一个完整的 epoll 示例,包括每个函数的原型、参数说明、返回值,以及一个完整的服务器示例代码。
epoll_create
函数原型
int epoll_create(int size); |
参数说明
-
size: 指定了epoll实例所能同时监控的文件描述符的数量。这个参数并不是限制最大并发数量,而是一个提示给内核的初始大小。
返回值
-
成功时,返回一个新的 epoll 实例的文件描述符。
-
错误时,返回 -1,并设置
errno以指示错误。
epoll_create1
函数原型
int epoll_create1(int flags); |
参数说明
-
flags: 可以是以下标志的组合:EPOLL_CLOEXEC: 设置close-on-exec属性。0:无特殊行为
返回值
-
成功时,返回一个新的 epoll 实例的文件描述符。
-
错误时,返回 -1,并设置
errno以指示错误。
epoll_ctl
函数原型
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); |
参数说明
-
epfd: epoll 实例的文件描述符。 -
op: 操作类型,可以是EPOLL_CTL_ADD(添加)、EPOLL_CTL_MOD(修改)或EPOLL_CTL_DEL(删除)。 -
fd: 要操作的文件描述符。 -
event: 指向epoll_event结构体的指针,包含了要设置的事件和用户数据。
返回值
-
成功时,返回 0。
-
错误时,返回 -1,并设置
errno以指示错误。
epoll_wait
函数原型
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout); |
参数说明
-
epfd: epoll 实例的文件描述符。 -
events: 指向epoll_event结构体数组的指针,用于接收发生的事件。 -
maxevents:events数组的最大容量。 -
timeout: 等待时间,单位为毫秒。-1 表示无限期等待。
返回值
-
成功时,返回数组中已填充的事件数量。
-
错误时,返回 -1,并设置
errno以指示错误。
epoll_event 结构体
struct epoll_event { |
epoll 服务器示例
|
练习
-
file server 用epoll改写一下