poll实现I/O多路复用

poll函数原型


参数说明:

fds:是一个struct pollfd结构类型的数组,用于存放需要检测其状态的Socket描述符;每当调用这个函数之后,系统不会清空这个数组,操作起来比较方便;特别是对于socket连接比较多的情况下,在一定程度上可以提高处理的效率;这一点与select()函数不同,调用select()函数之后,select()函数会清空它所检测的socket描述符集合,导致每次调用select()之前都必须把socket描述符重新加入到待检测的集合中;因此,select()函数适合于只检测一个socket描述符的情况,而poll()函数适合于大量socket描述符的情况;

nfds:nfds_t类型的参数,用于标记数组fds中的结构体元素的总数量;

timeout:是poll函数调用阻塞的时间,单位:毫秒;

如果timeout==0,那么poll() 函数立即返回而不阻塞,如果timeout==INFTIM(宏 表示为-1),那么poll() 函数会一直阻塞下去,直到所检测的socket描述符上的感兴趣的事件发生是才返回

函数返回值:

    poll函数的返回值与select函数的返回值一样。

    若返回0:表示超时

    若为-1:错误

    若>0:返回就绪事件的个数

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<poll.h>

int main(int argc,char* argv[])
{
//    if(argc !=3)
//    {
//        printf("Usage #: %s [ip] [port]\n",argv[0]);
//        exit(1);
//    }


    //创建数组,用以指定我们感兴趣的文件描述符上发生的可读、可写和异常等事件
//    struct pollfd
//    {
//      int fd; //件描述符
//      short events; //注册的事件
//      short revents; //``实际发生的事件,由内核填充,输出型
//    };

    struct pollfd fds[2]; //文件描述符
    fds[0].fd=0;
    fds[0].events=POLLIN; //对读事件感兴趣
    fds[0].revents=0;//输出型

    fds[1].fd=1;
    fds[1].events=POLLOUT;//对写事件感兴趣
    fds[1].revents=0;

    char buf[1024];
    int done=0;
    int i=0;

    int timeout=5000;//5000毫秒,即5秒

    while(!done)
    {
        int ret=poll(fds,sizeof(fds)/sizeof(fds[0]),timeout);
        switch(ret)
        {
            case -1:
                perror("poll");
                exit(2);
                break;
            case 0:
                printf("timeout...\n");
                break;
            default:
                //有事件就绪,但还需判断是哪个文件描述符的什么事件
                for(i=0;i<sizeof(fds)/sizeof(fds[0]);++i)
                {
                    //是否可读
                    //fds[i]所关心的事件是读,而是有读事件发生
                    if(fds[i].fd==0&&(fds[i].revents & POLLIN))
                    {
                        memset(buf,'\0',sizeof(buf));
                        ssize_t _s=read(0,buf,sizeof(buf)-1);
                        if(_s>0)
                        {
                            buf[_s -1]='\0';
                            if(strncmp(buf,"quit",4)==0)
                            {
                                close(fds[i].fd);
                                exit(0);
                            }
                            printf("echo#:%s\n",buf);
                        }
                    }
                     if(fds[i].fd==1&&(fds[i].revents & POLLOUT))
                    {
                        memset(buf,'\0',sizeof(buf));
                        strcpy(buf,"mengxiangjia");
                        printf("echo#:%s\n",buf);
                        sleep(3);
                    }
                }
                break;
        }
    }

    return 0;
}


poll函数的缺点:

(1)大量的fd的数组被整体复制于用户态和内核地址空间之间,而不管这样的复制是不是有意义。

(2)与select一样,poll返回后,需要轮询poolfd来获取就绪的描述符。


poll函数的优点:

(1)poll函数不要求计算最大文件描述符的大小

(2)poll函数在应付大数目的文件描述符的时候速度更快,相比于select

(3)它没有最大连接数的限制,原因是它基于链表来存储的。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值