• 使用select处理任意数目个客户的单进程程序


    改写http://www.cnblogs.com/nufangrensheng/p/3587962.html中的TCP回射服务器程序,把它重写成使用select来处理任意数目个客户的单进程程序,而不是为每个客户派生一个子进程。

    int 
    main(int argc, char **argv)
    {
        int                   i, maxi, maxfd, listenfd, connfd, sockfd;
        int                   nready, client[FD_SETSIZE];
        ssize_t               n;
        fd_set                rset, allset;
        char                  buf[4096];
        socklen_t             clilen;
        struct sockaddr_in    cliaddr, servaddr;
    
        listenfd = socket(AF_INET, SOCK_STREAM, 0);
        
        bzero(&servaddr, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
        servaddr.sin_port = htons(9877);
        
        bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
        
        listen(listenfd, 5);
    
        maxfd = listenfd;
        maxi = -1;
        for(i = 0; i < FD_SETSIZE; i++)
            client[i] = -1;        /* -1 indicates available entry */
        FD_ZERO(&allset);
        FD_SET(listenfd, &allset);
    
        for(;;)
        {
            rset = allset;
            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;    /* save descriptor */
                        break;
                    }
                }
                if(i == FD_SETSIZE)
                {
                    printf("too many clients
    ");
                    exit(1);
                }
                FD_SET(connfd, &allset);    /* add new descriptor to set */
                if(connfd > maxfd)
                    maxfd = connfd;
                if(i > maxi)
                    maxi = i;
    
                if(--nready <= 0)
                    continue;    /* no more readable descriptor */
            }
    
            for(i = 0; i <= maxi; i++)    /* check all clients for data */
            {
                if((sockfd = client[i]) < 0)
                    continue;
                if(FD_ISSET(sockfd, &rset))
                {
                    if((n = read(sockfd, buf, 4096)) == 0)    /* connection closed by client */
                    {
                        close(sockfd);
                        FD_CLR(sockfd, &rset);
                        client[i] = -1;
                    }
                    else
                    {
                        writen(sockfd, buf, n);        
                    }
                    
                    if(--nready <= 0)    /* no more readable descriptors */
                        break;
                }
            }
        }
    }
  • 相关阅读:
    【php】session读写锁
    【php】set_include_path和get_include_path用法详解
    【php】header下载文件后,文件变大的问题;(ob_clean()清空缓存)
    php反射机制应用
    vue内置组件 transition 和 keep-alive 使用
    vue中$router以及$route的使用
    通过LxRunOffline迁移Win10的Linux子系统
    vue Router——进阶篇
    vue keep-alive
    go语法和特点零碎总结
  • 原文地址:https://www.cnblogs.com/nufangrensheng/p/3590002.html
Copyright © 2020-2023  润新知