博客首页 注册 建议与交流 排行榜 加入友情链接
推荐 投诉 搜索: 帮助

计算机资料&彩票

努力学习 推荐
wrtrtew.cublog.cn


最简单的Epoll模型代码
  1. /*  
  2. EPOLLOUT:表示对应的文件描述符可以写;   
  3. EPOLLPRI:表示对应的文件描述符有紧急的数据可读(我不太明白是什么意思,可能是类似client关闭 socket连接这样的事件);   
  4. EPOLLERR:表示对应的文件描述符发生错误;   
  5. EPOLLHUP:表示对应的文件描述符被挂断;   
  6. EPOLLET:表示对应的文件描述符有事件发生;   
  7. */  
  8. #include <iostream>   
  9. #include <sys/socket.h>   
  10. #include <sys/epoll.h>   
  11. #include <netinet/in.h>   
  12. #include <arpa/inet.h>   
  13. #include <fcntl.h>   
  14. #include <unistd.h>   
  15. #include <stdio.h>   
  16.   
  17. #define MAXLINE 10   
  18. #define OPEN_MAX 100   
  19. #define LISTENQ 20   
  20. #define SERV_PORT 5555   
  21. #define INFTIM 1000   
  22.   
  23. void setnonblocking(int sock)   
  24. {   
  25.      int opts;   
  26.      opts=fcntl(sock,F_GETFL);   
  27.      if(opts<0)   
  28.      {   
  29.           perror("fcntl(sock,GETFL)");   
  30.           exit(1);   
  31.      }   
  32.      opts = opts|O_NONBLOCK;   
  33.      if(fcntl(sock,F_SETFL,opts)<0)   
  34.      {   
  35.           perror("fcntl(sock,SETFL,opts)");   
  36.           exit(1);   
  37.      }       
  38. }   
  39. int main()   
  40. {   
  41.      int i, maxi, listenfd, connfd, sockfd,epfd,nfds;   
  42.      ssize_t n;   
  43.      char line[MAXLINE];   
  44.      socklen_t clilen;   
  45.      //声明epoll_event结构体的变量,ev用于注册事件,数组用于回传要处理的事件   
  46.      struct epoll_event ev,events[20];   
  47.      //生成用于处理accept的epoll专用的文件描述符   
  48.      epfd=epoll_create(256);   
  49.      struct sockaddr_in clientaddr;   
  50.      struct sockaddr_in serveraddr;   
  51.      listenfd = socket(AF_INET, SOCK_STREAM, 0);   
  52.      //把socket设置为非阻塞方式   
  53.      setnonblocking(listenfd);   
  54.      //设置与要处理的事件相关的文件描述符   
  55.      ev.data.fd=listenfd;   
  56.      //设置要处理的事件类型   
  57.      ev.events=EPOLLIN|EPOLLET;   
  58.      //注册epoll事件   
  59.      epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&ev); //相当于Select模型的FD_SET   
  60.      bzero(&serveraddr, sizeof(serveraddr));   
  61.      serveraddr.sin_family = AF_INET;   
  62.      char *local_addr="127.0.0.1";   
  63.      inet_aton(local_addr,&(serveraddr.sin_addr));//htons(SERV_PORT);   
  64.      serveraddr.sin_port=htons(SERV_PORT);   
  65.      bind(listenfd,(sockaddr *)&serveraddr, sizeof(serveraddr));   
  66.      listen(listenfd, LISTENQ);   
  67.      maxi = 0;    
  68.      for ( ; ; ) {   
  69.           //等待epoll事件的发生   
  70.           nfds=epoll_wait(epfd,events,20,500);   
  71.           //处理所发生的所有事件         
  72.           for(i=0;i<nfds;++i)   
  73.           {   
  74.                if(events[i].data.fd==listenfd)//有客户端连入   
  75.                {   
  76.                     connfd = accept(listenfd,(sockaddr *)&clientaddr, &clilen);   
  77.                     if(connfd<0){   
  78.                          perror("connfd<0");   
  79.                          exit(1);   
  80.                     }   
  81.                     setnonblocking(connfd);   
  82.                     char *str = inet_ntoa(clientaddr.sin_addr);   
  83.                     std::cout<<"connect from "<_u115 ?tr<<std::endl;   
  84.                     //设置用于读操作的文件描述符   
  85.                     ev.data.fd=connfd;   
  86.                     //设置用于注测的读操作事件   
  87.                     ev.events=EPOLLIN|EPOLLET;   
  88.                     //注册ev   
  89.                     epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&ev);   
  90.                }   
  91.                else if(events[i].events&EPOLLIN)   
  92.                {   
  93.                     if ( (sockfd = events[i].data.fd) < 0) continue;   
  94.                     if ( (n = read(sockfd, line, MAXLINE)) < 0) {   
  95.                          if (errno == ECONNRESET) {   
  96.                               close(sockfd);   
  97.                               events[i].data.fd = -1;   
  98.                          } else    
  99.                               std::cout<<"readline error"<<std::endl;   
  100.                     } else if (n == 0) {   
  101.                          close(sockfd);   
  102.                          events[i].data.fd = -1;   
  103.                     }   
  104.                     //设置用于写操作的文件描述符   
  105.                     ev.data.fd=sockfd;   
  106.                     //设置用于注测的写操作事件   
  107.                     ev.events=EPOLLOUT|EPOLLET;   
  108.                     //修改sockfd上要处理的事件为EPOLLOUT   
  109.                     epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev);   
  110.                }   
  111.                else if(events[i].events&EPOLLOUT)   
  112.                {       
  113.                     sockfd = events[i].data.fd;   
  114.                     write(sockfd, line, n);   
  115.                     //设置用于读操作的文件描述符   
  116.                     ev.data.fd=sockfd;   
  117.                     //设置用于注测的读操作事件   
  118.                     ev.events=EPOLLIN|EPOLLET;   
  119.                     //修改sockfd上要处理的事件为EPOLIN   
  120.                     epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev);   
  121.                }   
  122.           }   
  123.      }   
  124. }   

发表于: 2008-05-10 ,修改于: 2008-05-10 19:00,已浏览146次,有评论0条 推荐 投诉


网友评论

发表评论