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

  • 相关阅读:
    atitit.nfc 身份证 银行卡 芯片卡 解决方案 attilax总结
    atitit.php 流行框架 前三甲为:Laravel、Phalcon、Symfony2 attilax 总结
    Atitit.执行cmd 命令行 php
    Atitit. 图像处理jpg图片的压缩 清理垃圾图片 java版本
    atitit。企业组织与软件工程的策略 战略 趋势 原则 attilax 大总结
    atitit. 管理哲学 大毁灭 如何防止企业的自我毁灭
    Atitit.java的浏览器插件技术 Applet japplet attilax总结
    Atitit.jquery 版本新特性attilax总结
    Atitit. 软件开发中的管理哲学一个伟大的事业必然是过程导向为主 过程导向 vs 结果导向
    (转)获取手机的IMEI号
  • 原文地址:https://www.cnblogs.com/zhaoyl/p/4000607.html
Copyright © 2011-2022 走看看