IO複用----epoll的使用

三組函數

(1)創建內核事件表
只是給內核一個提示,事件表需要多大;
返回值:內核事件表的文件描述符,可以理解爲事件表紅黑樹的根;
在這裏插入圖片描述
(2)對內核事件表的增刪改操作
注意epoll_event的結構;
在這裏插入圖片描述

(3)等待事件發生
第二個參數爲已經就緒有事件發生的文件描述符集合**(與poll的區別就在此,poll只返回個數)**
在這裏插入圖片描述

poll和epoll的區別

在這裏插入圖片描述
代碼epoll的使用

  1 #include"wrap.h"
  2 #include<errno.h>
  3 #include<sys/epoll.h>
  4 #define MAX_EVENT_NUM  1024
  5 #define BUFF_SIZE 64
  6 
  7 void delfd (int epollfd ,int fd)
  8 {
  9     struct epoll_event event;
 10     event.events = EPOLLIN;
 11     event.data.fd = fd;
 12 
 13     epoll_ctl(epollfd,EPOLL_CTL_DEL,fd,&event);
 14 }
 15 void addfd(int epollfd , int fd)//fd做成結構體才能加入事件表
 16 {
 17     struct epoll_event event;
 18     event.events = EPOLLIN;
 19     event.data.fd = fd;
 20 
 21     epoll_ctl(epollfd,EPOLL_CTL_ADD,fd,&event);
 22 }
 23 int main(int argc , char * argv[])
 24 {
 25     if(argc  < 2 )
 26     {
 27         printf("輸入IP和端口\neg:./a.out 127.0.0.2 8000\n");
 28         exit(1);
 29     }
 30     const char * ip = argv[1];
 31     int port = atoi(argv[2]);
 32     struct sockaddr_in saddr,caddr;
 33 
 34     int sfd = Socket(AF_INET,SOCK_STREAM,0);
 35 
 36     bzero(&saddr,sizeof(saddr));
 37     saddr.sin_family = AF_INET;
 38     saddr.sin_port = htons(port);
 39     inet_pton(AF_INET,ip ,&saddr.sin_addr.s_addr);
 40     Bind(sfd,(struct sockaddr*)&saddr,sizeof(saddr));
 41 
 42     Listen(sfd,5);
 43 
 44     int epollfd =  epoll_create(5);//創建epoll事件表的期望大小,返回事件表的根,即紅黑樹的根;
 45     if(epollfd ==-1 )
 46       perr_exit("epoll_crete error");
 47 
 48     addfd(epollfd , sfd);//封裝函數,將監聽socket加入epoll事件表;
 49 
 50     struct epoll_event events[MAX_EVENT_NUM];//定義就緒事件容器;
 51     while(1)
 52     {
 53         int ret = epoll_wait(epollfd,events,MAX_EVENT_NUM,-1);
 54         if(ret < 0)
 55             perr_exit("epoll-wait error");
 56         int i;
 57         for(i=0; i < ret ; ++i)
 58         {
 59             if(!events[i].events & EPOLLIN)//只關注讀事件
 60               continue;
 61 
 62             if(events[i].data.fd == sfd )//監聽事件sfd分一類處理,接受客戶端;
 63             {
 64                 socklen_t len = sizeof(caddr);
 65                 int cfd = Accept(sfd,(struct sockaddr *)&caddr,&len);
 66                 char str[64];
 67                 printf("client cfd  ip =%s  port=%d\n",inet_ntop(AF_INET,&caddr.sin_addr.s_addr,
 68                         str,64),ntohs(caddr.sin_port));
 69                 addfd(epollfd, cfd);//客戶端放入監聽事件表中epoll來監聽;
 70             }
 71             else//其他客戶端cfd事件分一類處理,讀寫數據
 72             {
 73                 int sockfd = events[i].data.fd;//記錄一下cfd方便使用;
 74                 char buff[BUFF_SIZE];
 75                 memset(buff,'\0',BUFF_SIZE);
 76                 int n = recv(sockfd,buff,BUFF_SIZE-1,0);
 77                 if(n == 0)//對方關閉
 78                 {
 79                     printf("client %d closing...\n",sockfd);
 80                     delfd(epollfd,sockfd);
 81                     continue;
 82                 }
 83                 if(n < 0)//接受數據出錯
 84                 {
 85                     perror("client error");
 86                     delfd(epollfd,sockfd);
 87                     continue;
 88                 }
 89                 else//數據轉化,並且發送數據
 90                 {
 91                     int j=0;
 92                     for(j=0;j<n;++j)
 93                       buff[j]=toupper(buff[j]);
 94                     int n =send(sockfd,buff,BUFF_SIZE-1,0);
 95                     if( n<0)
 96                       perror("send error");
 97                 }
 98 
 99             }
100 
101         }
102     }
103 
104 
105     return 0;
106 }

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章