zoukankan      html  css  js  c++  java
  • 【网络编程】学习笔记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
  • 相关阅读:
    Luogu P1596 [USACO10OCT]湖计数Lake Counting
    Luogu P1757 通天之分组背包
    数据建模笔记1
    单纯形算法 matlab
    有效集 matlab代码
    拟牛顿 DFP matlab
    FR共轭梯度法 matlab
    整数规划
    线性规划 Matlab
    远期、期货和互换(三)
  • 原文地址:https://www.cnblogs.com/Anonytt/p/15547536.html
Copyright © 2011-2022 走看看