网络编程4:高并发服务器——多路I/O转接服务器设计(select、poll、epoll)

返回:Linux网络编程学习笔记

select、poll、epoll三者优缺点对比

多路I/O函数 优点 缺点
select 1.函数诞生时间早,跨平台性好,windows、linux、macOS、Unix、类Unix均支持 1.监听的文件描述符上限为1024;2.需要添加业务逻辑,来监听满足条件的fd,代码编程难度会提高(业务逻辑是指添加一个1024大小的数组,通过数组来管理满足条件的fd,详见代码)
poll 1.自带数组结构,可将监听和返回事件集合分离;2.可以拓展文件描述符监听上限,突破1024 1.不能跨平台,仅Linux支持;2.无法直接定位满足监听事件的文件描述符,编码难度较大
epoll 1.解决了监听事件难于管理的问题,编程比较简单;2.监听事件上限可以突破1024 1.不能跨平台,仅Linux支持。

 

1. select

1.1 select输入参数说明

       /* According to earlier standards */
       #include <sys/time.h>
       #include <sys/types.h>
       #include <unistd.h>

       int select(int nfds, fd_set *readfds, fd_set *writefds,
                  fd_set *exceptfds, struct timeval *timeout);

       void FD_CLR(int fd, fd_set *set);
       int  FD_ISSET(int fd, fd_set *set);
       void FD_SET(int fd, fd_set *set);
       void FD_ZERO(fd_set *set);

参数说明:
int nfds                       //监听的最大文件描述符+1,作为监听循环的上限
fd_set *read_fds,        //监视的可读文件句柄集合。
fd_set *write_fds,       //监视的可写文件句柄集合。
fd_set *excepr_fds,      //监视的异常文件句柄集合。
struct timeval *timeout  //本次select()的超时结束时间。

1.2 select函数使用方法

方法一:通过循环判断文件lfd+1到maxfd之间是否有读事件,来操作套接字的读和写。

缺点:效率比较低,在lfd+1到maxfd之间如果有文件关闭了,也会进入FD_ISSET的判断。

方法二:定义数组int client[1024],用来管理lfd+1到maxfd之间需要监听的文件,具体方法如下:

1.当lfd有读事件时会生成cfd,通过for循环查找靠前没有使用的client元素,使client[i]=cfd(未使用的client[i]会置-1);

2.在使用FD_ISSET之前,先判断client[i]是否大于0,大于0的情况才进行判断。

具体的操作如下:

参考链接:linux select函数详解

1.3 使用select函数实现多路I/O转发

详见底部代码

主要疑问:select函数实现的是一个非阻塞忙轮询的逻辑,accept函数为何不会阻塞?

原因很简单,下方代码在使用accept函数之前,首先通过FD_ISSET函数判断了listenfd是有读事件发生的,所以不阻塞。只有在listenfd没有读事件且使用accept函数的情况下,才会阻塞,通过条件判断规避了阻塞的情况。

        nready = select(maxfd+1, &rset, NULL, NULL, NULL);
        if (nready < 0)
            perr_exit("select error");

        if (FD_ISSET(listenfd, &rset)) {                        /* 说明有新的客户端链接请求 */

            clie_addr_len = sizeof(clie_addr);
            connfd = Accept(listenfd, (struct sockaddr *)&clie_addr, &clie_addr_len);       /* Accept 不会阻塞 */

            FD_SET(connfd, &allset);                            /* 向监控文件描述符集合allset添加新的文件描述符connfd */

            if (maxfd < connfd)
                maxfd = connfd;

            if (0 == --nready)                                  /* 只有listenfd有事件, 后续的 for 不需执行 */
                continue;
        } 

2. poll

2.1 poll函数输入参数说明

NAME
       poll, ppoll - wait for som
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

snaking616

你的鼓励是我最大的动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值