• select、poll、epoll程序实例


    三个函数的基本用法如下:

    select
      创建
          fd_set rset , allset;
          FD_ZERO(&allset);
          FD_SET(listenfd, &allset);
      监听
          /*只select出用于读的描述字,阻塞无timeout*/
          nready = select(maxfd+1 , &rset , NULL , NULL , NULL);
      获取
          if(FD_ISSET(listenfd,&rset))


    poll:

      创建
          struct pollfd client[OPEN_MAX];
          client[0].fd = listenfd;
          client[0].events = POLLRDNORM;
          for(i=1;i<OPEN_MAX;i++)
          {
            client[i].fd = -1;
          }
          maxi = 0;
      监听
           nready = poll(client,maxi+1,INFTIM);
      获取
          sockfd = client[i].fd;
          if(client[i].revents & (POLLRDNORM|POLLERR))


    epoll:

      创建
          int epfd;
          struct epoll_event ev, events[20];
          epfd = epoll_create(256);
          ev.data.fd=listenfd;
          ev.events=EPOLLIN|EPOLLET;
          epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&ev);
      监听
          nfds=epoll_wait(epfd,events,20,500);
      获取
          if (events[i].events & EPOLLIN)

    IO复用,说得粗鄙一点,就是不用开多线程也能发送和接收消息。不多说,看代码:(select和poll是别人写的。引用一下,别见怪。)

    select:

    #include <stdio.h>
    #include <string.h>
    #include <arpa/inet.h>
    #include <netinet/in.h>
    #include <sys/socket.h>
    #include <sys/select.h>
    
    const static int MAXLINE = 1024;
    const static int SERV_PORT = 10001;
    
    int main()
    {
        int i , maxi , maxfd, listenfd , connfd , sockfd ;
        /*nready 描述字的数量*/
        int nready ,client[FD_SETSIZE];
        int n ;
        /*创建描述字集合,由于select函数会把未有事件发生的描述字清零,所以我们设置两个集合*/
        fd_set rset , allset;
        char buf[MAXLINE];
        socklen_t clilen;
        struct sockaddr_in cliaddr , servaddr;
        /*创建socket*/
        listenfd = socket(AF_INET , SOCK_STREAM , 0);
        /*定义sockaddr_in*/
        memset(&servaddr , 0 ,sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_port = htons(SERV_PORT);
        servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    
        bind(listenfd, (struct sockaddr *) & servaddr , sizeof(servaddr));
        listen(listenfd , 100);
        /*listenfd 是第一个描述字*/
        /*最大的描述字,用于select函数的第一个参数*/
        maxfd = listenfd;
        /*client的数量,用于轮询*/
        maxi = -1;
        /*init*/
        for(i=0 ;i<FD_SETSIZE ; i++)
            client[i] = -1;
        FD_ZERO(&allset);
        FD_SET(listenfd, &allset);
    
        for (;;)
        {
            rset = allset;
            /*只select出用于读的描述字,阻塞无timeout*/
            nready = select(maxfd+1 , &rset , NULL , NULL , NULL);
            if(FD_ISSET(listenfd,&rset))
            {
                clilen = sizeof(cliaddr);
                connfd = accept(listenfd , (struct sockaddr *) & cliaddr , &clilen);
                /*寻找第一个能放置新的描述字的位置*/
                for (i=0;i<FD_SETSIZE;i++)
                {
                    if(client[i]<0)
                    {
                        client[i] = connfd;
                        break;
                    }
                }
                /*找不到,说明client已经满了*/
                if(i==FD_SETSIZE)
                {
                    printf("Too many clients , over stack .
    ");
                    return -1;
                }
                FD_SET(connfd,&allset);//设置fd
                /*更新相关参数*/
                if(connfd > maxfd) maxfd = connfd;
                if(i>maxi) maxi = i;
                if(nready<=1) continue;
                else nready --;
            }
    
            for(i=0 ; i<=maxi ; i++)
            {
                if (client[i]<0) continue;
                sockfd = client[i];
                if(FD_ISSET(sockfd,&rset))
                {
                    n = read(sockfd , buf , MAXLINE);
                    if (n==0)
                    {
                        /*当对方关闭的时候,server关闭描述字,并将set的sockfd清空*/
                        close(sockfd);
                        FD_CLR(sockfd,&allset);
                        client[i] = -1;
                    }
                    else
                    {
                        buf[n]='';
                        printf("Socket %d said : %s
    ",sockfd,buf);
                        write(sockfd,buf,n); //Write back to client
                    }
                    nready --;
                    if(nready<=0) break;
                }
            }
    
        }
        return 0;
    }

    poll:

    #include <stdio.h>
    #include <string.h>
    #include <arpa/inet.h>
    #include <netinet/in.h>
    #include <sys/socket.h>
    #include <poll.h>
     
    /*环境为ubuntu10.04自带c环境,无法自动引入下列宏,所以自己写在前面了*/
    #define INFTIM -1
    #define POLLRDNORM  0x040       /* Normal data may be read.  */
    #define POLLRDBAND  0x080       /* Priority data may be read.  */
    #define POLLWRNORM  0x100       /* Writing now will not block.  */
    #define POLLWRBAND  0x200       /* Priority data may be written.  */
     
    #define MAXLINE  1024
    #define OPEN_MAX  16 //一些系统会定义这些宏
    #define SERV_PORT  10001
     
    int main()
    {
        int i , maxi ,listenfd , connfd , sockfd ;
        int nready;
        int n;
        char buf[MAXLINE];
        socklen_t clilen;
        struct pollfd client[OPEN_MAX];
     
        struct sockaddr_in cliaddr , servaddr;
        listenfd = socket(AF_INET , SOCK_STREAM , 0);
        memset(&servaddr,0,sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_port = htons(SERV_PORT);
        servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
     
        bind(listenfd , (struct sockaddr *) & servaddr, sizeof(servaddr));
        listen(listenfd,10);
        client[0].fd = listenfd;
        client[0].events = POLLRDNORM;
        for(i=1;i<OPEN_MAX;i++)
        {
            client[i].fd = -1;
        }
        maxi = 0;
     
        for(;;)
        {
            nready = poll(client,maxi+1,INFTIM);
            if (client[0].revents & POLLRDNORM)
            {
                clilen = sizeof(cliaddr);
                connfd = accept(listenfd , (struct sockaddr *)&cliaddr, &clilen);
                for(i=1;i<OPEN_MAX;i++)
                {
                    if(client[i].fd<0)
                    {
                        client[i].fd = connfd;
                        client[i].events = POLLRDNORM;
                        break;
                    }
                }
                if(i==OPEN_MAX)
                {
                    printf("too many clients! 
    ");
                }
                if(i>maxi) maxi = i;
                nready--;
                if(nready<=0) continue;
            }
     
            for(i=1;i<=maxi;i++)
            {
                if(client[i].fd<0) continue;
                sockfd = client[i].fd;
                if(client[i].revents & (POLLRDNORM|POLLERR))
                {
                    n = read(client[i].fd,buf,MAXLINE);
                    if(n<=0)
                    {
                        close(client[i].fd);
                        client[i].fd = -1;
                    }
                    else
                    {
                        buf[n]='';
                        printf("Socket %d said : %s
    ",sockfd,buf);
                        write(sockfd,buf,n); //Write back to client
                    }
                    nready--;
                    if(nready<=0) break; //no more readable descriptors
                }
            }
        }
        return 0;
    }

    epoll:

    #include <stdio.h>
    #include <string.h>
    #include <arpa/inet.h>
    #include <netinet/in.h>
    #include <sys/socket.h>
    #include <poll.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    #include <unistd.h>
    #include <arpa/inet.h>
    #include <fcntl.h>
    #include <sys/epoll.h>
    #include <sys/time.h>
    #include <sys/resource.h>
     
    #define MAXLINE  1024
    #define OPEN_MAX  16 //一些系统会定义这些宏
    #define SERV_PORT  10001
     
    int main()
    {
        int i , maxi ,listenfd , connfd , sockfd ,epfd, nfds;
        int n;
        char buf[MAXLINE];
        struct epoll_event ev, events[20];  
        socklen_t clilen;
        struct pollfd client[OPEN_MAX];
     
        struct sockaddr_in cliaddr , servaddr;
        listenfd = socket(AF_INET , SOCK_STREAM , 0);
        memset(&servaddr,0,sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_port = htons(SERV_PORT);
        servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
     
        bind(listenfd , (struct sockaddr *) & servaddr, sizeof(servaddr));
        listen(listenfd,10);
        
        epfd = epoll_create(256);
        ev.data.fd=listenfd; 
        ev.events=EPOLLIN|EPOLLET;
        epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&ev);
        
        for(;;)
        {
            nfds=epoll_wait(epfd,events,20,500); 
            for(i=0; i<nfds; i++)
            {
                if (listenfd == events[i].data.fd)
                {
                    clilen = sizeof(cliaddr);
                    connfd = accept(listenfd , (struct sockaddr *)&cliaddr, &clilen);
                    if(connfd < 0)  
                    {  
                        perror("connfd < 0");  
                        exit(1);  
                    }
                    ev.data.fd=connfd; 
                    ev.events=EPOLLIN|EPOLLET;
                    epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&ev);                
                }
                else if (events[i].events & EPOLLIN)
                {
                    if ( (sockfd = events[i].data.fd) < 0)  
                        continue;  
                    n = recv(sockfd,buf,MAXLINE,0);
                    if (n <= 0)   
                    {    
                        close(sockfd);  
                        events[i].data.fd = -1;  
                    }
                    else
                    {
                        buf[n]='';
                        printf("Socket %d said : %s
    ",sockfd,buf);
                        ev.data.fd=sockfd; 
                        ev.events=EPOLLOUT|EPOLLET;
                        epoll_ctl(epfd,EPOLL_CTL_MOD,connfd,&ev);
                    }
                }
                else if( events[i].events&EPOLLOUT )
                {
                    sockfd = events[i].data.fd;  
                    send(sockfd, "Hello!", 7, 0);  
                      
                    ev.data.fd=sockfd;  
                    ev.events=EPOLLIN|EPOLLET;  
                    epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev); 
                }
                else 
                {
                    printf("This is not avaible!");
                }
            }
        }
        close(epfd);  
        return 0;
    }
  • 相关阅读:
    PHP面向对象编程入门
    PHP错误处理机制
    PHP数组深入
    PHP 表单
    多重背包之单调队列优化理论性总结
    二分查找理论性总结
    大连海事大学第十届程序设计竞赛 题解
    Codeforces Round #603 (Div. 2) E. Editor (线段树维护前缀和最值)
    Educational Codeforces Round 77 (Rated for Div. 2) E. Tournament (DP)
    Leetcode1256 加密数字(手动找规律)
  • 原文地址:https://www.cnblogs.com/bugutian/p/4816764.html
Copyright © 2020-2023  润新知