zoukankan      html  css  js  c++  java
  • 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 1000
    
    void 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
    ",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
    ";
                                    break;
                             }
                            else if (errno == EINTR)
                            {//有数据但未读到断了,所以要接着读
                                continue;
                            }
                            else
                            {
                                CloseAndDisable(sockfd, events[i]);
                                cout << "unrecovable error
    ";
                                break;
                            }
                       }
                       else if( recvNum == 0)
                       {
                            CloseAndDisable(sockfd, events[i]);
                            cout << "counterpart has shut off
    ";
                            break;
                       }
    
                       count += recvNum;
                       if ( recvNum == MAXLINE-1)
                       {
                       cout << "sleeping..."<<endl;
               sleep(5);
                           cout << "recvNum == MAXLINE-1
    "<<endl;
                           continue;
                       }
                       else // 0 < recvNum < MAXLINE-1
                       {
                           cout << "0 < recvNum < MAXLINE-1"<<endl;
                           bReadOk = true;
                           break; // 退出while(1),表示已经全部读完数据
                       }
    
                    }
    
                    if (bReadOk == true)
                    {
                        line[count] = '';
                        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
    ",sizeof(str));
                    memcpy(line, str, sizeof(str));
                    //cout << line << endl;
            printf("d %d u %u lu %lu
    ",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和accept的注意点,参见http://www.ccvita.com/515.html

  • 相关阅读:
    15、线程
    17、lambda表达式
    16、sockect
    14、反射(reflect)
    13、集合2
    java 基本类型、包装类、字符串之间的转换
    13、集合1
    12、NIO、AIO、BIO二
    12、NIO、AIO、BIO一
    11、流与文件
  • 原文地址:https://www.cnblogs.com/zhaoyl/p/4000607.html
Copyright © 2011-2022 走看看