linux epoll用法之二

    雖然epoll的api函數比較簡單,但是還是自己寫了一個epoll的封裝類,如下:

頭文件:

  1. //=============== Epoll.h =============== 
  2. #ifndef EPOLL_H_INCLUDED 
  3. #define EPOLL_H_INCLUDED 
  4.  
  5. #include <sys/epoll.h> 
  6. #include <unistd.h> 
  7.  
  8.  
  9. class Epoll 
  10. public
  11.     Epoll(int nFdCount, int nEventCount); 
  12.     ~Epoll(); 
  13.  
  14. public
  15.     void Create();      //create epoll 
  16.  
  17.     bool AddToEpoll(int fd, uint32_t events);        //add fd to epoll 
  18.     bool DelFromEpoll(int fd);                       //del fd from epoll 
  19.     bool Modify(int fd, uint32_t events);            //modify fd's events in epoll 
  20.  
  21. public
  22.     int Wait(int nTimeOut = -1);    //if nTimeOut is -1, will wait indefinitely 
  23.  
  24.     bool GetNextFd(int *pFd, uint32_t *pEvents); 
  25.     bool IsEof(); 
  26.  
  27. private
  28.     int m_epfd;         //fd of the real epoll 
  29.     int m_nFdCount;     //max size fd count in the epoll 
  30.     int m_nEventCount;  //event count for per wait operation 
  31.  
  32.     int m_nWaitFds;     //active fd count returned by wait() 
  33.     int m_nCurFdNum;    //the fd num that is processing 
  34.     bool m_bIsEof;      //eof ? 
  35.  
  36.     epoll_event *m_pEvents;     //internal epoll_events 
  37.  
  38. }; 
  39.  
  40. #endif // EPOLL_H_INCLUDED 

源文件:

 

  1. //============= Epoll.cpp ============== 
  2. #include <stdio.h> 
  3. #include "Epoll.h" 
  4.  
  5. Epoll::Epoll(int nFdCount, int nEventCount) : m_epfd(-1), m_nFdCount(nFdCount), 
  6.                                             m_nEventCount(nEventCount),m_pEvents(NULL), 
  7.                                             m_nWaitFds(0), m_nCurFdNum(0), m_bIsEof(false
  8.     m_pEvents = new epoll_event[nEventCount]; 
  9.     Create(); 
  10.  
  11. Epoll::~Epoll() 
  12.     if (m_epfd != -1) 
  13.     { 
  14.         close( m_epfd ); 
  15.     } 
  16.  
  17.     if(m_pEvents != NULL) 
  18.     { 
  19.         delete []m_pEvents; 
  20.     } 
  21.  
  22. void Epoll::Create() 
  23.     m_epfd = epoll_create( m_nFdCount ); 
  24.     if (m_epfd < 0) 
  25.     { 
  26.         printf("create epoll failed !!\n"); 
  27.         return
  28.     } 
  29.     //printf("create epoll success !!\n"); 
  30.     return
  31.  
  32. bool Epoll::AddToEpoll(int fd, uint32_t events) 
  33.     epoll_event ev; 
  34.     ev.data.fd = fd; 
  35.     ev.events = events; 
  36.  
  37.     int ret = epoll_ctl(m_epfd, EPOLL_CTL_ADD, fd, &ev); 
  38.     if(ret < 0) 
  39.     { 
  40.         printf("add fd to epoll failed !!\n"); 
  41.         return false
  42.     } 
  43.     //printf("add fd to epoll success !!\n"); 
  44.     return true
  45.  
  46. bool Epoll::DelFromEpoll(int fd) 
  47.     epoll_event tmpEvent;   //In kernel versions before 2.6.9, 
  48.                             //event pointer must not be null 
  49.     int ret = epoll_ctl(m_epfd, EPOLL_CTL_DEL, fd, &tmpEvent); 
  50.     if(ret < 0) 
  51.     { 
  52.         printf("del fd from epoll failed !!\n"); 
  53.         return false
  54.     } 
  55.     //printf("del fd from epoll success !!\n"); 
  56.     return false
  57.  
  58. bool Epoll::Modify(int fd, uint32_t events) 
  59.     epoll_event ev; 
  60.     ev.data.fd = fd; 
  61.     ev.events = events; 
  62.  
  63.     int ret = epoll_ctl(m_epfd, EPOLL_CTL_MOD, fd, &ev); 
  64.     if (ret < 0) 
  65.     { 
  66.         printf("mod the epfd failed !!\n"); 
  67.         return false
  68.     } 
  69.     //printf("mod the epfd success !!\n"); 
  70.     return true
  71.  
  72. int Epoll::Wait(int nTimeOut) 
  73.     int nFds = epoll_wait(m_epfd, m_pEvents, m_nEventCount, nTimeOut); 
  74.     if (nFds < 0) 
  75.     { 
  76.         printf("epoll wait error !!\n"); 
  77.         return -1; 
  78.     } 
  79.     m_nWaitFds = nFds; 
  80.     m_nCurFdNum = 0;    //reset the cur fd num 
  81.     m_bIsEof = false;   //reset eof flag 
  82.  
  83.     return nFds; 
  84.  
  85. bool Epoll::GetNextFd(int *pFd, uint32_t *pEvents) 
  86.     if (pEvents == NULL) 
  87.     { 
  88.         return false
  89.     } 
  90.  
  91.     *pFd = m_pEvents[m_nCurFdNum].data.fd; 
  92.     *pEvents = m_pEvents[m_nCurFdNum].events; 
  93.  
  94.     m_nCurFdNum ++; 
  95.     if (m_nCurFdNum >= m_nWaitFds) 
  96.     { 
  97.         m_bIsEof = true
  98.     } 
  99.  
  100.     return true
  101.  
  102. bool Epoll::IsEof() 
  103.     return m_bIsEof; 

下面是應用實例,還是隻是最簡單的單線程server:

 

  1. //============== server.cpp ============== 
  2. #include <stdio.h> 
  3. #include <fcntl.h> 
  4. #include <string.h> 
  5. #include <unistd.h> 
  6. #include <errno.h> 
  7.  
  8. #include <sys/types.h> 
  9. #include <sys/socket.h> 
  10. #include <netinet/in.h> 
  11. #include <arpa/inet.h> 
  12.  
  13. #include "Epoll.h" 
  14.  
  15. const int SERV_PORT = 20000; 
  16. const int LISTEN_BACKLOG = 10; 
  17. const int EPOLL_SIZE = 100; 
  18. const int EPOLL_EVENTS_SIZE = 20; 
  19.  
  20.  
  21. void setnonblocking(int sockfd) 
  22.     int flags = fcntl(sockfd, F_GETFL, 0); 
  23.     fcntl(sockfd, F_SETFL, flags|O_NONBLOCK); 
  24.     //printf("set nonblock success !!\n"); 
  25.  
  26.     return
  27.  
  28. void setreuseaddr(int sockfd) 
  29.     int rep = 1; 
  30.     int ret = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &rep, sizeof(rep) ); 
  31.     if(ret < 0) 
  32.     { 
  33.         printf("set reuse addr failed !!\n"); 
  34.         return
  35.     } 
  36.     //printf("set reuse addr success !!\n"); 
  37.     return
  38.  
  39. int main() 
  40.     int servfd; 
  41.     int ret; 
  42.  
  43.     //create socket 
  44.     servfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //TCP SOCKET 
  45.     if(servfd < 0)      //or == -1 
  46.     { 
  47.         printf("create socket failed !!\n"); 
  48.         return -1; 
  49.     } 
  50.     //printf("create socket success !!\n"); 
  51.  
  52.     //set non block 
  53.     setnonblocking(servfd); 
  54.  
  55.     //set reuseaddr 
  56.     setreuseaddr(servfd); 
  57.  
  58.     //init the serv addr struct 
  59.     struct sockaddr_in servAddr; 
  60.     memset(&servAddr, 0, sizeof(servAddr) ); 
  61.     servAddr.sin_family = AF_INET; 
  62.     servAddr.sin_port = htons( SERV_PORT ); 
  63.     servAddr.sin_addr.s_addr = htons( INADDR_ANY ); 
  64.  
  65.     //bind 
  66.     ret = bind(servfd, (struct sockaddr*)&servAddr, sizeof(servAddr) ); 
  67.     if(ret < 0) 
  68.     { 
  69.         printf("bind failed !!\n"); 
  70.         close(servfd); 
  71.         return -1; 
  72.     } 
  73.     //printf("bind success !!\n"); 
  74.  
  75.     //listen 
  76.     ret = listen(servfd, LISTEN_BACKLOG); 
  77.     if(ret < 0) 
  78.     { 
  79.         printf("listen failed !!\n"); 
  80.         close(servfd); 
  81.         return -1; 
  82.     } 
  83.     printf("begin to listen ... \n"); 
  84.  
  85.     //create epoll 
  86.     Epoll epoll(EPOLL_SIZE, EPOLL_EVENTS_SIZE); 
  87.     printf("epoll create success !!\n"); 
  88.  
  89.     //add servfd to epoll 
  90.     uint32_t events = EPOLLIN | EPOLLET; 
  91.     epoll.AddToEpoll(servfd, events); 
  92.     printf("add servfd to epoll success !!\n\n"); 
  93.  
  94.  
  95.     while(true
  96.     { 
  97.         int nfds = epoll.Wait(500); 
  98.         if(nfds < 0)    //error happens 
  99.         { 
  100.             printf("wait error !!\n"); 
  101.             close(servfd); 
  102.             return -1; 
  103.         } 
  104.         if(nfds == 0)   //wait timeout 
  105.         { 
  106.             printf("epoll wait timeout !!\n"); 
  107.             sleep(1); 
  108.             continue
  109.         } 
  110.         //printf("\n%d requests to process ... \n", nfds); 
  111.  
  112.         while ( !epoll.IsEof() ) 
  113.         { 
  114.             int tmpfd = -1; 
  115.             uint32_t events ; 
  116.  
  117.             epoll.GetNextFd(&tmpfd, &events); 
  118.             if (tmpfd == -1) 
  119.             { 
  120.                 printf("epoll getnext fd failed !!\n"); 
  121.                 continue
  122.             } 
  123.  
  124.             if(tmpfd == servfd) 
  125.             { 
  126.                 printf("accept ... \n"); 
  127.  
  128.                 struct sockaddr_in cliaddr; 
  129.                 memset(&cliaddr, 0, sizeof(cliaddr) ); 
  130.                 socklen_t addrlen = sizeof(cliaddr); 
  131.  
  132.                 //accept connect 
  133.                 int confd = accept(servfd, (struct sockaddr*)&cliaddr, &addrlen); 
  134.                 if(confd < 0) 
  135.                 { 
  136.                     printf("accept failed !!\n"); 
  137.                     close(servfd); 
  138.                     return -1; 
  139.                 } 
  140.                 //printf("accept success !!\n"); 
  141.                 printf("client address : %s--%d \n\n", inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port)); 
  142.  
  143.                 //set non block 
  144.                 setnonblocking(confd); 
  145.  
  146.                 int events = EPOLLET | EPOLLIN; 
  147.                 bool ret = epoll.AddToEpoll(confd, events); 
  148.                 //if (ret) 
  149.                     //printf("add confd to epoll success !!\n"); 
  150.             } 
  151.             else 
  152.             { 
  153.                 //printf("other request ... \n"); 
  154.  
  155.                 if(events&EPOLLIN != 0) 
  156.                 { 
  157.                     printf("begin recv ... \n"); 
  158.  
  159.                     char msg[1024*10] = {0}; 
  160.                     int nMsg = 0; 
  161.                     while(true
  162.                     { 
  163.                         char temp[1024] = {0}; 
  164.                         int nrecv = recv(tmpfd, temp, 1024, 0); 
  165.                         if(nrecv < 0) 
  166.                         { 
  167.                             if(errno == EAGAIN) //non block, recv again 
  168.                             { 
  169.                                 //printf("eagain, all data has recved !!\n", errno); 
  170.                                 break
  171.                             } 
  172.                             else 
  173.                             { 
  174.                                 printf("recv error , errno is %d !!\n", errno); 
  175.                                 close( tmpfd ); 
  176.                                 close( servfd ); 
  177.                                 return -1; 
  178.                             } 
  179.  
  180.                         } 
  181.                         if(nrecv == 0) 
  182.                         { 
  183.                             break
  184.                         } 
  185.  
  186.                         memcpy(msg, temp, nrecv); 
  187.                         nMsg += nrecv; 
  188.                     } 
  189.                     printf("recved %d bytes : %s \n\n", nMsg, msg); 
  190.  
  191.                     int events = EPOLLET | EPOLLOUT; 
  192.                     bool ret = epoll.Modify(tmpfd, events); 
  193.                     if(ret < 0) 
  194.                     { 
  195.                         printf("modify recvfd failed !!\n"); 
  196.                         close( tmpfd ); 
  197.                         close( servfd ); 
  198.                         return -1; 
  199.                     } 
  200.                     //printf("modify recvfd for send success !! \n"); 
  201.                 } 
  202.                 else if((events&EPOLLOUT) != 0) 
  203.                 { 
  204.                     printf("begin to send ... \n"); 
  205.  
  206.                     int clifd = tmpfd; 
  207.  
  208.                     char pmsg[1024] = {0}; 
  209.                     sprintf(pmsg, "%s""copy it !!"); 
  210.                     int msglen = strlen( pmsg ); 
  211.  
  212.                     int nsend = send(clifd, pmsg, msglen, 0); 
  213.                     if(nsend <= 0) 
  214.                     { 
  215.                         printf("send error !!\n"); 
  216.                         close(servfd); 
  217.                         close(clifd); 
  218.                         return -1; 
  219.                     } 
  220.                     printf("send success : %d bytes!!\n\n", nsend); 
  221.  
  222.                     close(clifd); 
  223.  
  224.                 } 
  225.             } 
  226.         } 
  227.  
  228.         usleep( 100 ); 
  229.     } 
  230.  
  231.     close(servfd); 
  232.     return 1; 

 

                                                                                                       ----  2012.11.13 23:47

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