首页 > 代码库 > epoll示例

epoll示例

书到用时方恨少,一切尽在不言中
#include <iostream>#include <sys/socket.h>#include <sys/epoll.h>#include <netinet/in.h>#include <arpa/inet.h>#include <fcntl.h>#include <unistd.h>#include <stdio.h>#include <errno.h>#include <string.h>using namespace std;#define MAXLINE 5#define OPEN_MAX 100#define LISTENQ 20#define SERV_PORT 5000#define INFTIM 1000void setnonblocking(int sock){    int opts;    opts=fcntl(sock,F_GETFL);    if(opts<0)    {        perror("fcntl(sock,GETFL)");        return;    }    opts = opts|O_NONBLOCK;    if(fcntl(sock,F_SETFL,opts)<0)    {        perror("fcntl(sock,SETFL,opts)");        return;    }}void CloseAndDisable(int sockid, epoll_event ee){    close(sockid);    ee.data.fd = -1;}ssize_t socket_send(int sockfd, const char* buffer, size_t buflen){  ssize_t tmp;  size_t total = buflen;  const char *p = buffer;  while(1)  {     tmp = send(sockfd, p, total, 0);     if(tmp < 0)     {        if(errno == EINTR)            return -1;        if(errno == EAGAIN)        {           usleep(1000);           continue;        }           return -1;     }         if((size_t)tmp == total)         return buflen;     total -= tmp;     p += tmp;   }   return tmp;}int main(){    int i, maxi, listenfd, connfd, sockfd,epfd,nfds, portnumber;    char line[MAXLINE*50];    socklen_t clilen;    portnumber = 5000;    struct epoll_event ev,events[20];    epfd=epoll_create(256);        struct sockaddr_in clientaddr;    struct sockaddr_in serveraddr;    listenfd = socket(AF_INET, SOCK_STREAM, 0);    memset(&serveraddr, 0, sizeof(serveraddr));    serveraddr.sin_family = AF_INET;    serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);    serveraddr.sin_port=htons(portnumber);    bind(listenfd,(sockaddr *)&serveraddr, sizeof(serveraddr));    listen(listenfd, LISTENQ);    ev.data.fd=listenfd;    ev.events=EPOLLIN|EPOLLET;    epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&ev);    maxi = 0;    int bOut = 0;    for ( ; ; )    {        if (bOut == 1)            break;        nfds=epoll_wait(epfd,events,20,-1);        //printf("wait %d returns\n",nfds);        for(i=0;i<nfds;++i)        {                    if(events[i].data.fd==listenfd)//如果新监测到一个SOCKET用户连接到了绑定的SOCKET端口            {                connfd = accept(listenfd,(sockaddr *)&clientaddr, &clilen);                if(connfd<0){                    perror("connfd<0");                    return (1);                }                                char *str = inet_ntoa(clientaddr.sin_addr);                cout << "accapt a connection from " << str << endl;                setnonblocking(connfd);                ev.data.fd=connfd;                ev.events=EPOLLIN | EPOLLET;                //注册ev                epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&ev);            }            else if(events[i].events & EPOLLIN)            {                cout << "EPOLLIN" << endl;                if ( (sockfd = events[i].data.fd) < 0)                    continue;                cout << "START READ" << endl;                char * head = line;                int recvNum = 0;                int count = 0;                bool bReadOk = false;                while(1)                {                    recvNum = recv(sockfd, head+count, MAXLINE-1, 0);                    if(recvNum < 0)                    {                        if(errno == EAGAIN)                        {//已没数据 不阻塞等待                            bReadOk = true;                            break;                        }                        else if (errno == ECONNRESET)                        {                                CloseAndDisable(sockfd, events[i]);                                cout << "counterpart send out RST\n";                                break;                         }                        else if (errno == EINTR)                        {//有数据但未读到断了,所以要接着读                            continue;                        }                        else                        {                            CloseAndDisable(sockfd, events[i]);                            cout << "unrecovable error\n";                            break;                        }                   }                   else if( recvNum == 0)                   {                        CloseAndDisable(sockfd, events[i]);                        cout << "counterpart has shut off\n";                        break;                   }                   count += recvNum;                   if ( recvNum == MAXLINE-1)                   {                   cout << "sleeping..."<<endl;           sleep(5);                       cout << "recvNum == MAXLINE-1\n"<<endl;                       continue;                   }                   else // 0 < recvNum < MAXLINE-1                   {                       cout << "0 < recvNum < MAXLINE-1"<<endl;                       bReadOk = true;                       break; // 退出while(1),表示已经全部读完数据                   }                }                if (bReadOk == true)                {                    line[count] = \0;                    cout << "we have read from the client : " << line;                    ev.data.fd=sockfd;                    ev.events = EPOLLOUT | EPOLLET;                    epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev);                }            }            else if(events[i].events & EPOLLOUT) // 如果有数据发送            {                cout << "EPOLLOUT" << endl;                const char str[] = "1234567890";        //printf("%d\n",sizeof(str));                memcpy(line, str, sizeof(str));                //cout << line << endl;        printf("d %d u %u lu %lu\n",i,i,i);                sockfd = events[i].data.fd;                int bWritten = 0;                int writenLen = 0;                int count = 0;                char * head = line;        bWritten=socket_send(sockfd,head,strlen(head));                if (bWritten == strlen(head))                {                    ev.data.fd=sockfd;                    ev.events=EPOLLIN | EPOLLET;                    epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev);                }            }        }    }    return 0;}

 

epoll示例