Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3472010
  • 博文数量: 1450
  • 博客积分: 11163
  • 博客等级: 上将
  • 技术积分: 11101
  • 用 户 组: 普通用户
  • 注册时间: 2005-07-25 14:40
文章分类

全部博文(1450)

文章存档

2017年(5)

2014年(2)

2013年(3)

2012年(35)

2011年(39)

2010年(88)

2009年(395)

2008年(382)

2007年(241)

2006年(246)

2005年(14)

分类: LINUX

2008-06-16 18:53:32

epoll用到的所有函数都是在头文件sys/epoll.h中声明的,下面简要说明所用到的数据结构和函数:
所用到的数据结构
  1. typedef union epoll_data {  
  2.                 void *ptr;  
  3.                 int fd;  
  4.                 __uint32_t u32;  
  5.                 __uint64_t u64;  
  6.         } epoll_data_t;  
  7.   
  8.         struct epoll_event {  
  9.                 __uint32_t events;      /* Epoll events */  
  10.                 epoll_data_t data;      /* User data variable */  
  11.         };  

结构体epoll_event 被用于注册所感兴趣的事件和回传所发生待处理的事件,其中epoll_data 联合体用来保存触发事件的某个文件描述符相关的数据,例如一个client连接到服务器,服务器通过调用accept函数可以得到于这个client对应 的socket文件描述符,可以把这文件描述符赋给epoll_data的fd字段以便后面的读写操作在这个文件描述符上进行。epoll_event 结构体的events字段是表示感兴趣的事件和被触发的事件可能的取值为:
  1. EPOLLIN :表示对应的文件描述符可以读;  
  2. EPOLLOUT:表示对应的文件描述符可以写;  
  3. EPOLLPRI:表示对应的文件描述符有紧急的数据可读(这里应该表示有带外数据到来);  
  4. EPOLLERR:表示对应的文件描述符发生错误;  
  5. EPOLLHUP:表示对应的文件描述符被挂断;  
  6. EPOLLET:表示对应的文件描述符有事件发生;  

所用到的函数:
1、epoll_create函数
     函数声明:int epoll_create(int size)
    该函数生成一个epoll专用的文件描述符,其中的参数是指定生成描述符的最大范围(我觉得这个参数和select函数的第一个参数应该是类似的但是该怎么设置才好,我也不太清楚)。
2、epoll_ctl函数
     函数声明:int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
     该函数用于控制某个文件描述符上的事件,可以注册事件,修改事件,删除事件。
    参数:epfd:由 epoll_create 生成的epoll专用的文件描述符;
                op:要进行的操作例如注册事件,可能的取值EPOLL_CTL_ADD 注册、EPOLL_CTL_MOD 修
                        改、EPOLL_CTL_DEL 删除
                fd:关联的文件描述符;
                event:指向epoll_event的指针;
    如果调用成功返回0,不成功返回-1
3、epoll_wait函数
函数声明:int epoll_wait(int epfd,struct epoll_event * events,int maxevents,int timeout)
该函数用于轮询I/O事件的发生;
参数:
epfd:由epoll_create 生成的epoll专用的文件描述符;
epoll_event:用于回传代处理事件的数组;
maxevents:每次能处理的事件数;
timeout:等待I/O事件发生的超时值;
返回发生事件数。
例子:



  1. #include   
  2.   
  3. #include   
  4.   
  5. #include   
  6.   
  7. #include   
  8.   
  9. #include   
  10.   
  11. #include   
  12.   
  13. #include   
  14.   
  15. #include   
  16.   
  17.    
  18.   
  19. #define MAXLINE 10  
  20.   
  21. #define OPEN_MAX 100  
  22.   
  23. #define LISTENQ 20  
  24.   
  25. #define SERV_PORT 5555  
  26.   
  27. #define INFTIM 1000  
  28.   
  29.    
  30.   
  31. void setnonblocking(int sock)  
  32.   
  33. {  
  34.   
  35.      int opts;  
  36.   
  37.      opts=fcntl(sock,F_GETFL);  
  38.   
  39.      if(opts<0)  
  40.   
  41.      {  
  42.   
  43.           perror("fcntl(sock,GETFL)");  
  44.   
  45.           exit(1);  
  46.   
  47.      }  
  48.   
  49.      opts = opts|O_NONBLOCK;  
  50.   
  51.      if(fcntl(sock,F_SETFL,opts)<0)  
  52.   
  53.      {  
  54.   
  55.           perror("fcntl(sock,SETFL,opts)");  
  56.   
  57.           exit(1);  
  58.   
  59.      }      
  60.   
  61. }  
  62.   
  63.    
  64.   
  65. int main()  
  66.   
  67. {  
  68.   
  69.      int i, maxi, listenfd, connfd, sockfd,epfd,nfds;  
  70.   
  71.      ssize_t n;  
  72.   
  73.      char line[MAXLINE];  
  74.   
  75.      socklen_t clilen;  
  76.   
  77.      //声明epoll_event结构体的变量,ev用于注册事件,数组用于回传要处理的事件  
  78.   
  79.      struct epoll_event ev,events[20];  
  80.   
  81.      //生成用于处理accept的epoll专用的文件描述符  
  82.   
  83.      epfd=epoll_create(256);  
  84.   
  85.    
  86.   
  87.      struct sockaddr_in clientaddr;  
  88.   
  89.      struct sockaddr_in serveraddr;  
  90.   
  91.      listenfd = socket(AF_INET, SOCK_STREAM, 0);  
  92.   
  93.      //把socket设置为非阻塞方式  
  94.   
  95.      setnonblocking(listenfd);  
  96.   
  97.      //设置与要处理的事件相关的文件描述符  
  98.   
  99.      ev.data.fd=listenfd;  
  100.   
  101.      //设置要处理的事件类型  
  102.   
  103.      ev.events=EPOLLIN|EPOLLET;  
  104.   
  105.      //注册epoll事件  
  106.   
  107.      epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&ev);  
  108.   
  109.    
  110.   
  111.      bzero(&serveraddr, sizeof(serveraddr));  
  112.   
  113.      serveraddr.sin_family = AF_INET;  
  114.   
  115.    
  116.   
  117.      char *local_addr="200.200.200.204";  
  118.   
  119.      inet_aton(local_addr,&(serveraddr.sin_addr));//htons(SERV_PORT);  
  120.   
  121.      serveraddr.sin_port=htons(SERV_PORT);  
  122.   
  123.      bind(listenfd,(sockaddr *)&serveraddr, sizeof(serveraddr));  
  124.   
  125.      listen(listenfd, LISTENQ);  
  126.   
  127.    
  128.   
  129.      maxi = 0;   
  130.   
  131.      for ( ; ; ) {  
  132.   
  133.           //等待epoll事件的发生  
  134.   
  135.           nfds=epoll_wait(epfd,events,20,500);  
  136.   
  137.           //处理所发生的所有事件        
  138.   
  139.           for(i=0;i
  140.   
  141.           {  
  142.   
  143.                if(events[i].data.fd==listenfd)  
  144.   
  145.                {  
  146.   
  147.    
  148.   
  149.                     connfd = accept(listenfd,(sockaddr *)&clientaddr, &clilen);  
  150.   
  151.                     if(connfd<0){  
  152.   
  153.                          perror("connfd<0");  
  154.   
  155.                          exit(1);  
  156.   
  157.                     }  
  158.   
  159.                     setnonblocking(connfd);  
  160.   
  161.    
  162.   
  163.                     char *str = inet_ntoa(clientaddr.sin_addr);  
  164.                     //这里修改了部分,应该是str  
  165.                     std::cout<<"connect from < 
  166.  
  167.  
  168.                     //设置用于读操作的文件描述符 
  169.  
  170.                     ev.data.fd=connfd; 
  171.  
  172.                     //设置用于注测的读操作事件 
  173.  
  174.                     ev.events=EPOLLIN|EPOLLET; 
  175.  
  176.                     //注册ev 
  177.  
  178.                     epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&ev); 
  179.  
  180.                } 
  181.  
  182.                else if(events[i].events&EPOLLIN) 
  183.  
  184.                { 
  185.  
  186.                     if ( (sockfd = events[i].data.fd) < 0) continue; 
  187.  
  188.                     if ( (n = read(sockfd, line, MAXLINE)) < 0) { 
  189.                          //这里修改了,errno没有定义,ECONNRESET没有定义 
  190.                 /* 
  191.                          if (errno == ECONNRESET) { 
  192.  
  193.   
  194.  
  195.                               close(sockfd); 
  196.  
  197.                               events[i].data.fd = -1; 
  198.  
  199.                          } else  
  200.  
  201.                               std::cout<<"readline error"<
  202.                         */  
  203.   
  204.                     } else if (n == 0) {  
  205.   
  206.                          close(sockfd);  
  207.   
  208.                          events[i].data.fd = -1;  
  209.   
  210.                     }  
  211.   
  212.                     //设置用于写操作的文件描述符  
  213.   
  214.                     ev.data.fd=sockfd;  
  215.   
  216.                     //设置用于注测的写操作事件  
  217.   
  218.                     ev.events=EPOLLOUT|EPOLLET;  
  219.   
  220.                     //修改sockfd上要处理的事件为EPOLLOUT  
  221.   
  222.                     epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev);  
  223.   
  224.                }  
  225.   
  226.                else if(events[i].events&EPOLLOUT)  
  227.   
  228.                {      
  229.   
  230.                     sockfd = events[i].data.fd;  
  231.   
  232.                     write(sockfd, line, n);  
  233.   
  234.                     //设置用于读操作的文件描述符  
  235.   
  236.                     ev.data.fd=sockfd;  
  237.   
  238.                     //设置用于注测的读操作事件  
  239.   
  240.                     ev.events=EPOLLIN|EPOLLET;  
  241.   
  242.                     //修改sockfd上要处理的事件为EPOLIN  
  243.   
  244.                     epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev);  
  245.   
  246.                }  
  247.   
  248.    
  249.   
  250.           }  
  251.   
  252.    
  253.   
  254.      }  
  255.   
  256. }  


这样可以编译通过了!
阅读(878) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~