• 【网络编程】学习笔记06 I/O多路复用之epoll


    epoll是Linux下多路复用IO接口select/poll的增强版本,它能显著提高程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率,因为它会复用文件描述符集合来传递结果而不用迫使开发者每次等待事件之前都必须重新准备要被监听的文件描述符集合,另一个原因就是获取事件的时候,它无需遍历整个被监听的描述符集,只要遍历那些被IO事件唤醒而加入ready队列的描述符即可。

     

    epoll的server端:

     1 #include<stdio.h>
     2 #include<stdlib.h>
     3 #include<string.h>
     4 #include<unistd.h>
     5 #include<errno.h>
     6 #include<pthread.h>
     7 #include<ctype.h>
     8 #include<sys/socket.h>
     9 #include<sys/epoll.h>
    10 #include<arpa/inet.h>
    11 
    12 #define SERV_PORT 9527
    13 #define MAXLINE 8192
    14 #define OPEN_MAX 5000
    15 
    16 int main(int argc,char *argv[])
    17 {
    18     int listenfd = 0,connfd = 0,sockfd,i;
    19     int n,num = 0;
    20     ssize_t nready,efd,res;
    21     char buf[MAXLINE], str[INET_ADDRSTRLEN];
    22     socklen_t clilen;
    23 
    24     struct sockaddr_in cliaddr,servaddr;
    25 
    26     listenfd = socket(AF_INET,SOCK_STREAM,0);
    27     int opt = 1;
    28     setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));  //端口复用
    29     memset(&servaddr,0,sizeof(servaddr));
    30     servaddr.sin_family = AF_INET;
    31     servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    32     servaddr.sin_port = htons(SERV_PORT);
    33     bind(listenfd,(struct sockaddr *)&servaddr, sizeof(servaddr));
    34     listen(listenfd,20);
    35 
    36     efd = epoll_create(OPEN_MAX);    //创建epoll模型,efd指向红黑树根节点
    37 
    38     struct epoll_event tep, ep[OPEN_MAX];       //tep:epoll_ctl参数,ep[]:epoll_wait参数;
    39     tep.events = EPOLLIN;
    40     tep.data.fd = listenfd;                     //指定listenfd的监听事件为“读”
    41 
    42     res = epoll_ctl(efd, EPOLL_CTL_ADD, listenfd, &tep); //将listenfd及对应的结构体设置到树上,efd可找到该树
    43 
    44     for(;;){
    45         //epoll为server阻塞监听事件,ep为struct epoll_event类型数组,OPEN_MAX为数组容量,-1表示永久阻塞
    46         nready = epoll_wait(efd,ep,OPEN_MAX,-1);
    47 
    48         for(i=0;i<nready;i++){
    49             if(!(ep[i].events & EPOLLIN))
    50                 continue;
    51             if(ep[i].data.fd == listenfd){      //判断满足事件的fd是不是lfd
    52                 clilen = sizeof(cliaddr);
    53                 connfd = accept(listenfd,(struct sockaddr *)&cliaddr,&clilen); //接受连接
    54 
    55                 tep.events = EPOLLIN; 
    56                 tep.data.fd = connfd;
    57 
    58                 res = epoll_ctl(efd,EPOLL_CTL_ADD,connfd,&tep);  //加入红黑树
    59             }else{                      //不是lfd
    60                 sockfd = ep[i].data.fd;
    61                 n = read(sockfd,buf,MAXLINE);
    62 
    63                 if(n == 0){                                            //读到0,说明客户端关闭连接
    64                     res = epoll_ctl(efd, EPOLL_CTL_DEL, sockfd, NULL); //将该文件描述符从红黑树摘除
    65                     close(sockfd);                                     //关闭与该客户端的连接
    66                 }
    67                 else if(n < 0){        //出错
    68                     res = epoll_ctl(efd, EPOLL_CTL_DEL, sockfd, NULL); //摘除节点
    69                     close(sockfd);
    70                 }
    71                 else{                  //读到了字节数
    72                     for(i=0;i<n;i++)
    73                        buf[i] = toupper(buf[i]);
    74 
    75                     write(STDOUT_FILENO,buf,n);
    76                     write(sockfd,buf,n);
    77                 }
    78             }
    79         }
    80     }
    81     close(listenfd);
    82     return 0;
    83 }
    View Code
    前ICPC算法竞赛退役选手|现摸鱼ing
  • 相关阅读:
    jquery ajax 返回数据时 ff正常,ie接受到数据但是显示不了
    查看IIS日志并且分析其中的错误日志
    用eventvwr查看系统日志
    C++实现Trie 树
    [算法之美笔记02] 栈模拟网页的前进后退 ; 阻塞队列与并发队列
    MySQL学习小记(三) 结合JDBC实现用户的登录响应
    [算法之美笔记01] 数组,链表的删除和垃圾回收,缓存机制有什么关系
    [埋坑系列] 基于QT/C++的杰瑞走迷宫小游戏 :1.大体构造
    品味C++实现AVL树的删除操作
    C++实现AVL树的四种旋转
  • 原文地址:https://www.cnblogs.com/Anonytt/p/15547536.html
Copyright © 2020-2023  润新知