雖然epoll的api函數比較簡單,但是還是自己寫了一個epoll的封裝類,如下:
頭文件:
- //=============== Epoll.h ===============
- #ifndef EPOLL_H_INCLUDED
- #define EPOLL_H_INCLUDED
- #include <sys/epoll.h>
- #include <unistd.h>
- class Epoll
- {
- public:
- Epoll(int nFdCount, int nEventCount);
- ~Epoll();
- public:
- void Create(); //create epoll
- bool AddToEpoll(int fd, uint32_t events); //add fd to epoll
- bool DelFromEpoll(int fd); //del fd from epoll
- bool Modify(int fd, uint32_t events); //modify fd's events in epoll
- public:
- int Wait(int nTimeOut = -1); //if nTimeOut is -1, will wait indefinitely
- bool GetNextFd(int *pFd, uint32_t *pEvents);
- bool IsEof();
- private:
- int m_epfd; //fd of the real epoll
- int m_nFdCount; //max size fd count in the epoll
- int m_nEventCount; //event count for per wait operation
- int m_nWaitFds; //active fd count returned by wait()
- int m_nCurFdNum; //the fd num that is processing
- bool m_bIsEof; //eof ?
- epoll_event *m_pEvents; //internal epoll_events
- };
- #endif // EPOLL_H_INCLUDED
源文件:
- //============= Epoll.cpp ==============
- #include <stdio.h>
- #include "Epoll.h"
- Epoll::Epoll(int nFdCount, int nEventCount) : m_epfd(-1), m_nFdCount(nFdCount),
- m_nEventCount(nEventCount),m_pEvents(NULL),
- m_nWaitFds(0), m_nCurFdNum(0), m_bIsEof(false)
- {
- m_pEvents = new epoll_event[nEventCount];
- Create();
- }
- Epoll::~Epoll()
- {
- if (m_epfd != -1)
- {
- close( m_epfd );
- }
- if(m_pEvents != NULL)
- {
- delete []m_pEvents;
- }
- }
- void Epoll::Create()
- {
- m_epfd = epoll_create( m_nFdCount );
- if (m_epfd < 0)
- {
- printf("create epoll failed !!\n");
- return;
- }
- //printf("create epoll success !!\n");
- return;
- }
- bool Epoll::AddToEpoll(int fd, uint32_t events)
- {
- epoll_event ev;
- ev.data.fd = fd;
- ev.events = events;
- int ret = epoll_ctl(m_epfd, EPOLL_CTL_ADD, fd, &ev);
- if(ret < 0)
- {
- printf("add fd to epoll failed !!\n");
- return false;
- }
- //printf("add fd to epoll success !!\n");
- return true;
- }
- bool Epoll::DelFromEpoll(int fd)
- {
- epoll_event tmpEvent; //In kernel versions before 2.6.9,
- //event pointer must not be null
- int ret = epoll_ctl(m_epfd, EPOLL_CTL_DEL, fd, &tmpEvent);
- if(ret < 0)
- {
- printf("del fd from epoll failed !!\n");
- return false;
- }
- //printf("del fd from epoll success !!\n");
- return false;
- }
- bool Epoll::Modify(int fd, uint32_t events)
- {
- epoll_event ev;
- ev.data.fd = fd;
- ev.events = events;
- int ret = epoll_ctl(m_epfd, EPOLL_CTL_MOD, fd, &ev);
- if (ret < 0)
- {
- printf("mod the epfd failed !!\n");
- return false;
- }
- //printf("mod the epfd success !!\n");
- return true;
- }
- int Epoll::Wait(int nTimeOut)
- {
- int nFds = epoll_wait(m_epfd, m_pEvents, m_nEventCount, nTimeOut);
- if (nFds < 0)
- {
- printf("epoll wait error !!\n");
- return -1;
- }
- m_nWaitFds = nFds;
- m_nCurFdNum = 0; //reset the cur fd num
- m_bIsEof = false; //reset eof flag
- return nFds;
- }
- bool Epoll::GetNextFd(int *pFd, uint32_t *pEvents)
- {
- if (pEvents == NULL)
- {
- return false;
- }
- *pFd = m_pEvents[m_nCurFdNum].data.fd;
- *pEvents = m_pEvents[m_nCurFdNum].events;
- m_nCurFdNum ++;
- if (m_nCurFdNum >= m_nWaitFds)
- {
- m_bIsEof = true;
- }
- return true;
- }
- bool Epoll::IsEof()
- {
- return m_bIsEof;
- }
下面是應用實例,還是隻是最簡單的單線程server:
- //============== server.cpp ==============
- #include <stdio.h>
- #include <fcntl.h>
- #include <string.h>
- #include <unistd.h>
- #include <errno.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include "Epoll.h"
- const int SERV_PORT = 20000;
- const int LISTEN_BACKLOG = 10;
- const int EPOLL_SIZE = 100;
- const int EPOLL_EVENTS_SIZE = 20;
- void setnonblocking(int sockfd)
- {
- int flags = fcntl(sockfd, F_GETFL, 0);
- fcntl(sockfd, F_SETFL, flags|O_NONBLOCK);
- //printf("set nonblock success !!\n");
- return;
- }
- void setreuseaddr(int sockfd)
- {
- int rep = 1;
- int ret = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &rep, sizeof(rep) );
- if(ret < 0)
- {
- printf("set reuse addr failed !!\n");
- return;
- }
- //printf("set reuse addr success !!\n");
- return;
- }
- int main()
- {
- int servfd;
- int ret;
- //create socket
- servfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //TCP SOCKET
- if(servfd < 0) //or == -1
- {
- printf("create socket failed !!\n");
- return -1;
- }
- //printf("create socket success !!\n");
- //set non block
- setnonblocking(servfd);
- //set reuseaddr
- setreuseaddr(servfd);
- //init the serv addr struct
- struct sockaddr_in servAddr;
- memset(&servAddr, 0, sizeof(servAddr) );
- servAddr.sin_family = AF_INET;
- servAddr.sin_port = htons( SERV_PORT );
- servAddr.sin_addr.s_addr = htons( INADDR_ANY );
- //bind
- ret = bind(servfd, (struct sockaddr*)&servAddr, sizeof(servAddr) );
- if(ret < 0)
- {
- printf("bind failed !!\n");
- close(servfd);
- return -1;
- }
- //printf("bind success !!\n");
- //listen
- ret = listen(servfd, LISTEN_BACKLOG);
- if(ret < 0)
- {
- printf("listen failed !!\n");
- close(servfd);
- return -1;
- }
- printf("begin to listen ... \n");
- //create epoll
- Epoll epoll(EPOLL_SIZE, EPOLL_EVENTS_SIZE);
- printf("epoll create success !!\n");
- //add servfd to epoll
- uint32_t events = EPOLLIN | EPOLLET;
- epoll.AddToEpoll(servfd, events);
- printf("add servfd to epoll success !!\n\n");
- while(true)
- {
- int nfds = epoll.Wait(500);
- if(nfds < 0) //error happens
- {
- printf("wait error !!\n");
- close(servfd);
- return -1;
- }
- if(nfds == 0) //wait timeout
- {
- printf("epoll wait timeout !!\n");
- sleep(1);
- continue;
- }
- //printf("\n%d requests to process ... \n", nfds);
- while ( !epoll.IsEof() )
- {
- int tmpfd = -1;
- uint32_t events ;
- epoll.GetNextFd(&tmpfd, &events);
- if (tmpfd == -1)
- {
- printf("epoll getnext fd failed !!\n");
- continue;
- }
- if(tmpfd == servfd)
- {
- printf("accept ... \n");
- struct sockaddr_in cliaddr;
- memset(&cliaddr, 0, sizeof(cliaddr) );
- socklen_t addrlen = sizeof(cliaddr);
- //accept connect
- int confd = accept(servfd, (struct sockaddr*)&cliaddr, &addrlen);
- if(confd < 0)
- {
- printf("accept failed !!\n");
- close(servfd);
- return -1;
- }
- //printf("accept success !!\n");
- printf("client address : %s--%d \n\n", inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port));
- //set non block
- setnonblocking(confd);
- int events = EPOLLET | EPOLLIN;
- bool ret = epoll.AddToEpoll(confd, events);
- //if (ret)
- //printf("add confd to epoll success !!\n");
- }
- else
- {
- //printf("other request ... \n");
- if(events&EPOLLIN != 0)
- {
- printf("begin recv ... \n");
- char msg[1024*10] = {0};
- int nMsg = 0;
- while(true)
- {
- char temp[1024] = {0};
- int nrecv = recv(tmpfd, temp, 1024, 0);
- if(nrecv < 0)
- {
- if(errno == EAGAIN) //non block, recv again
- {
- //printf("eagain, all data has recved !!\n", errno);
- break;
- }
- else
- {
- printf("recv error , errno is %d !!\n", errno);
- close( tmpfd );
- close( servfd );
- return -1;
- }
- }
- if(nrecv == 0)
- {
- break;
- }
- memcpy(msg, temp, nrecv);
- nMsg += nrecv;
- }
- printf("recved %d bytes : %s \n\n", nMsg, msg);
- int events = EPOLLET | EPOLLOUT;
- bool ret = epoll.Modify(tmpfd, events);
- if(ret < 0)
- {
- printf("modify recvfd failed !!\n");
- close( tmpfd );
- close( servfd );
- return -1;
- }
- //printf("modify recvfd for send success !! \n");
- }
- else if((events&EPOLLOUT) != 0)
- {
- printf("begin to send ... \n");
- int clifd = tmpfd;
- char pmsg[1024] = {0};
- sprintf(pmsg, "%s", "copy it !!");
- int msglen = strlen( pmsg );
- int nsend = send(clifd, pmsg, msglen, 0);
- if(nsend <= 0)
- {
- printf("send error !!\n");
- close(servfd);
- close(clifd);
- return -1;
- }
- printf("send success : %d bytes!!\n\n", nsend);
- close(clifd);
- }
- }
- }
- usleep( 100 );
- }
- close(servfd);
- return 1;
- }
---- 2012.11.13 23:47