6、epoll多路IO

epoll多路IO

1、poll函数的参数

int poll(strucf pollfd  *fds, nfds_t nfds, int timeout);
/*
		fds:监听的文件描述数组
		struct pollfd
		{
			int fd;
			short events;//传入事件,取值POLLIN,POLLOUT,POLLERROR
			short revents;//传出事件,传入时给0,。如果满足对应事件的话,返回非0
						  //POLLIN,POLLOUT,POLLERRO
		}
		nfds:监听数组的实际有效监听个数
		timeout:超时时长,单位:毫秒(-1,阻塞等待;0,立即返回; >0:等待时长)
		返回值:返回满足对应监听的文件描述符的总个数
*/

2、poll函数使用的注意事项

server
poll
cfd1
cfd2
cfd3
struct pollfd pfds[1024];
pfds[0].fd = lfd;
pfds[0].events = POLLIN;
pfds[0].revents = 0;

pfds[1].fd = lfd;
pfds[1].events = POLLIN;
pfds[1].revents = 0;

pfds[2].fd = lfd;
pfds[2].events = POLLIN;
pfds[2].revents = 0;

while(1)
{
    int ret = poll(pfds,5,-1);
    for(i = 0; i < 5; i++)
    {
     	if(pfds[i].revents & POLLIN)
        {
            accept();//如果是lfd
            /***如果是cfd***/
            write()/read();
        }
    }
}

3、poll总结

优点:自带数组结构,可以将监听时间和返回事件集合

​ 可以扩展监听上限(select监听上限无法修改,但是poll可以修改监听上限)

缺点:不能跨平台,只能在linux下用

​ 无法直接定位满足监听事件文件描述符,编码难度较大

4、突破1024限制

突破1024文件描述符限制:

cat  /proc/sys/fs/file-max;     //当前计算机所能打开的最大文件个数,受硬件影响 
ulimit -a;//当前用户下的进程,默认打开文件
cat /proc/sys/fs/file-max  //查看一个socket能打开的fd上限

5、epoll函数

创建红黑树:

int epoll_create(int size);//打开一个句柄,文件描述符指向一个平衡二叉树,即epfd
//size指创建红黑树的监听节点的数量。(仅供内核参考)
//返回指,指向平衡二叉树的跟节点,失败就是-1
epfd
lfd
cdf2
cfd1

监听红黑树:

int epollctl(int epfd, int op, int fd, struct epoll_event *event);
//用来控制红黑树
//op表示对红黑树所做的操作
//	EPOLL_CTL_ADD  添加fd到监听红黑树
//  EPOLL_CTL_MOD  修改fd在红黑树的监听事件
//	EPOLL_CTL_DEL  摘下fd
//fd表示待监听的fd
//event: 本质上是struct epoll_event 结构体地址
//	events:  EPOLLIN/EPOLLOUT/EPOLLERR
//  data:联合体  int fd:	对应监听事件的fd
//				void *ptr: 泛型指针
//              uint32_t  u32;
//              uint64_t  u64;
//返回值: 成功0;失败 -1 eorr

阻塞红黑树:

int epoll_wait(int epfd, struct epoll_events *events, int maxevents, int timeout);
//epfd:  句柄
//events:  [数组],传出参数,满足监听条件的那些fd结构体
//用epoll监听的话监听的就不止是lfd,有数组就不需要轮询所有fd时间了
//maxevents:数组中元素的总数量
//timeout:-1阻塞,0:不阻塞,>0超时时间
//返回值:
//   > 0:满足监听的总个数。可以用作循环上限
//    0 :没有fd满足事件
//    -1:出错

6、epoll多路IO的代码实现

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<arpa/inet.h>
#include<sys/epoll.h>
#include<errno.h>
#include<ctype.h>

#define MAXLINE  8192
#define SERV_PORT 8000
#define OPEN_MAX 5000

int main(int argc, char *argv[])
{
    int i,lfd,cfd,sockfd;
    int n,num = 0;
    size_t nready,efd,res;
    char buf[MAXLINE],str[INET6_ADDRSTRLEN];
    socklen_t clien;

    struct sockaddr_in cliaddr,servaddr;
    struct epoll_event tep, ep[OPEN_MAX];//epoll_ctl para

    lfd = socket(AF_INET,SOCK_STREAM,0);
    int opt = 1;
    setsockopt(lfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));//port reuse
    bzero(&servaddr,sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(SERV_PORT);
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    bind(lfd,(struct sockaddr *) &servaddr, sizeof(servaddr));
    listen(lfd,20);
    efd = epoll_create(OPEN_MAX);
    tep.events = EPOLLIN; tep.data.fd = lfd;
    res = epoll_ctl(efd,EPOLL_CTL_ADD,lfd,&tep);
    for(;;)
    {
        nready = epoll_wait(efd,ep,OPEN_MAX,-1);
        for(i = 0; i < nready; i++)
        {
            if(!(ep[i].events & EPOLLIN))
                continue;
            if(ep[i].data.fd == lfd)
            {
                clien = sizeof(cliaddr);
                cfd = accept(lfd,(struct sockaddr *)&cliaddr, &clien);
                tep.events = EPOLLIN;
                tep.data.fd = cfd;
                res = epoll_ctl(efd,EPOLL_CTL_ADD,cfd,&tep);
            }
            else
            {   
                sockfd = ep[i].data.fd;
                n = read(sockfd,buf,MAXLINE);
                if(n <= 0)
                {
                    res = epoll_ctl(efd,EPOLL_CTL_DEL,sockfd,NULL);
                    close(sockfd);
                }
                else
                {
                    for(i = 0; i < n; i++)
                    {
                        buf[i] = toupper(buf[i]);
                    }
                    write(STDOUT_FILENO,buf,n);
                    write(sockfd,buf,n);
                }
            }
        }
    }
    close(lfd);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值