zoukankan      html  css  js  c++  java
  • select的限制与poll的使用

    select的限制

    select的并发数受到两个限制:1.一个进程能打开的最大描述符数量;2.select中fd_set集合容量的限制(FD_SETSIZE)

    关于进程的最大描述符数量:
    ulimit -n:查看一个进程能打开的最大描述符数量
    ulimit -n 2048:将最大描述符数量更改为2048,其它数量也可以,需root权限

    //最大描述符测试,如果数量是1024的情况下,不出意外程序会在i=1021时达到最大值,因为0,1,2被标准输入输出占有
    int main(int argc,char *argv[]){
        int i=0;
        while(1){
            int sockfd;
            struct sockaddr_in servaddr;
            char buf[1024];
     
            if((sockfd=socket(PF_INET,SOCK_STREAM,0)) < 0){
                printf("%d
    ",i);
                err_quit("socket");
            }
     
            bzero(&servaddr,sizeof(servaddr));
            servaddr.sin_family=AF_INET;
            servaddr.sin_addr.s_addr=inet_addr("127.0.0.1");
            servaddr.sin_port=htons(5566);
     
            int ret;
            ret=connect_timeout(sockfd,&servaddr,5);
            if(ret == -1 && errno == ETIMEDOUT){
                puts("timeout ...");
                return 1;
            }else if(ret == -1)
                err_quit("connect");
     
            bzero(buf,sizeof(buf));
            printf("%d
    ",++i);
        }
    }
    

    关于FD_SETSIZE的最大集合:
    上面的客户端同时开三个连接上一版的服务器,过一会儿就能看到效果,程序会在accept返回-1

    poll的使用

    #include <unistd.h>
    #include <poll.h>
    #include <netdb.h>
    #include <errno.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <signal.h>
    #include <sys/wait.h>
    #include <sys/select.h>
    #include <sys/socket.h>
    #include <arpa/inet.h>
    #include <netinet/in.h>
     
    #define MAX(a,b) a>b?a:b;
     
    void err_quit(const char *s){
        perror(s);
        exit(1);
    }
     
    ssize_t readn(int fd,void *buff,size_t count){
        char *buffp;
        ssize_t nread;
        size_t nleft;
     
        buffp=(char *)buff;
        nleft=count;
        while(nleft > 0){
            if((nread = read(fd,buffp,nleft)) < 0){
                if(errno == EINTR)
                    continue;
                else
                    return -1;
            }else if(nread == 0)
                break;
            nleft -= nread;
            buffp += nread;
        }
        return count-nleft;
    }
     
    ssize_t writen(int fd,const void *buff,size_t n){
        size_t nleft;
        ssize_t nwritten;
        const char *ptr;
     
        ptr=buff;
        nleft=n;
        while(nleft > 0){
            if((nwritten=write(fd,ptr,nleft)) < 0){
                if(nwritten < 0 && errno == EINTR)
                    continue;
                else
                    return -1;
            }else if(nwritten == 0)
                break;
            nleft -= nwritten;
            ptr += nwritten;
        }
        return n-nleft;
    }
     
    ssize_t recv_peek(int fd,void *buf,size_t len){
        ssize_t ret;
        while(1){
            ret=recv(fd,buf,len,MSG_PEEK);
            if(ret == -1 && errno == EINTR)
                continue;
            return ret;
        }
    }
     
    ssize_t readline(int fd,void *buf,size_t maxline){
        ssize_t ret;
        size_t nread;
        size_t nleft;
        char *bufp;
     
        bufp=buf;
        nleft=maxline;
        while(1){
            ret=recv_peek(fd,buf,nleft);
            if(ret < 0)
                return ret;
            else if(ret == 0)
                return ret;
     
            nread=ret;
            int i;
            for(i=0;i<nread;i++){
                if(bufp[i] == '
    '){
                    ret=readn(fd,bufp,i+1);
                    if(ret != i+1)
                        err_quit("readn");
     
                    return ret;
                }
            }
     
            if(nread > nleft)
                err_quit("readn");
     
            nleft -= nread;
            ret=readn(fd,bufp,nread);
            if(ret != nread)
                err_quit("readn");
     
            bufp += nread;
        }
     
        return -1;
    }
     
    int accept_timeout(int fd,struct sockaddr_in *addr,unsigned int wait_seconds){
        int ret;
        socklen_t addrlen=sizeof(struct sockaddr_in);
     
        if(wait_seconds > 0){
            fd_set accept_fdset;
            struct timeval timeout;
     
            FD_ZERO(&accept_fdset);
            FD_SET(fd,&accept_fdset);
     
            timeout.tv_usec=0;
            timeout.tv_sec=wait_seconds;
            do{
                ret=select(fd+1,&accept_fdset,NULL,NULL,&timeout);
            }while(ret < 0 && errno == EINTR);
     
            if(ret == 0){
                errno = ETIMEDOUT;
                return -1;
            }else if(ret == -1)
                return -1;
        }
     
        if(addr != NULL)
            ret=accept(fd,(struct sockaddr *)addr,&addrlen);
        else
            ret=accept(fd,NULL,NULL);
        if(ret == -1)
            err_quit("accept");
     
        return ret;
    }
     
    int main(int argc,char *argv[]){
        int i,maxi,tmpfd,sockfd,connfd;
        socklen_t len;
        struct sockaddr_in addr,client;
        int nready;
        struct pollfd clientfd[2048];
        ssize_t n;
        char buf[1024];
     
        if((sockfd=socket(PF_INET,SOCK_STREAM,0)) < 0)
            err_quit("sockfd");
     
        bzero(&addr,sizeof(addr));
        addr.sin_family=AF_INET;
        addr.sin_addr.s_addr=htonl(INADDR_ANY);
        addr.sin_port=htons(5566);
     
        int on=1;
        if(setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)) <0)
            err_quit("setsockopt");
     
        if(bind(sockfd,(struct sockaddr *)&addr,sizeof(addr))<0)
            err_quit("bind");
     
        if(listen(sockfd,10)<0)
            err_quit("listen");
     
        maxi=0;
        for(i=0;i<2048;i++)
            clientfd[i].fd=-1;
     
        clientfd[0].fd=sockfd;
        clientfd[0].events= POLLIN;
        while(1){
            nready=poll(clientfd,maxi+1,-1);
     
            if(nready == -1){
                if(errno == EINTR)
                    continue;
                else
                    err_quit("select");
            }
     
            if(clientfd[0].revents & POLLIN){
                len=sizeof(client);
                connfd=accept(sockfd,(struct sockaddr *)&client,&len);
                if(connfd < 0)
                    err_quit("accept");
     
                for(i=0;i<2048;i++){
                    if(clientfd[i].fd < 0){
                        clientfd[i].fd=connfd;
                        clientfd[i].events=POLLIN;
                        if(i > maxi)
                            maxi=i;
                        break;
                    }
                }
                if(i == 2048)
                    err_quit("too many clients");
     
                if(--nready <= 0)
                    continue;
            }
     
     
            for(i=1;i<=maxi;i++){
                if((tmpfd=clientfd[i].fd) < 0)
                    continue;
                if(clientfd[i].revents & POLLIN){
                    bzero(buf,sizeof(buf));
                    if((n=readline(tmpfd,buf,sizeof(buf))) == 0){
                        close(tmpfd);
                        clientfd[i].fd=-1;
                    }
                    write(STDOUT_FILENO,buf,n);
                    writen(tmpfd,buf,n);
     
                    if(--nready <= 0)
                        break;
                }
            }
        }
    }
    
  • 相关阅读:
    android动画(一)Interpolator
    android端手机测试体系 (转)
    Android的一些常用命令提示符(cmd)指令[转]
    五招避开银行小额账户管理费[转]
    WEB服务器、应用程序服务器、HTTP服务器区别[转]
    如何解决 “invalid resource directory name”, resource “crunch”[转]
    Eclipse中给jar包导入JavaDoc的方法
    rotium(无源码)获取控件较简单的办法
    基于Robotium框架的测试工程如何导入Robotium包的源码
    常用模块中函数的作用
  • 原文地址:https://www.cnblogs.com/cfans1993/p/6131892.html
Copyright © 2011-2022 走看看