slecte实例

2018-08-20  本文已影响0人  有何不可12317

基础知识参见IO复用基础-slecte-poll-epoll

#define MAXLINE 1028        // 接收配置更新指令的缓冲区大小
#define IP_ADDRSTRLEN 128
int deal_update(int listenfd)
{
    int i     = 0;
    int n     = 0;
    int maxi  = -1; 
    int maxfd = listenfd;
    int client[FD_SETSIZE]; /* FD_SETSIZE 默认为 1024 */
    int connfd, sockfd;
    int nready;

    char buf[MAXLINE];
    char clientIp[IP_ADDRSTRLEN];
    fd_set rset, allset;

    for(i = 0; i < FD_SETSIZE; i++)
        client[i] = -1; 

    FD_ZERO(&allset);
    FD_SET(listenfd, &allset);

    while(1)
    {
        rset = allset;
        struct timeval timeout = {0, 400 * 1000};

        nready = select(maxfd + 1, &rset, NULL, NULL, &timeout);
        if (nready < 0)
            perror("select error");


        if (FD_ISSET(listenfd, &rset))
        {   
            /* new client connection */
            struct sockaddr_in cliaddr;
            socklen_t cliaddr_len = sizeof(cliaddr);

            if ((connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len)) < 0) {
                printf("accept error\n");
                continue;
            }   

            inet_ntop(AF_INET, &cliaddr.sin_addr, clientIp, IP_ADDRSTRLEN);
            printf("received from %s at PORT %d\n", clientIp, ntohs(cliaddr.sin_port));

            // 将连接描述符加入到select的数组中
            for (i = 0; i < FD_SETSIZE; i++) {
                if (client[i] < 0) {
                    client[i] = connfd;
                    break;  // end for
                }
            }

            /* 
             * 达到select能监控的文件个数上限 1024 
             * 当达到上限的时候
             * */
            if (i == FD_SETSIZE) {
                fputs("too many clients\n", stderr);
                for (i = FD_SETSIZE; i < 1 ; i--) {
                    if (client[i] > 0) {
                        FD_CLR(client[i], &allset);
                        close(client[i]);
                    }
                }
                continue;
            }

            /* 添加一个新的文件描述符到监控信号集里 */
            FD_SET(connfd, &allset);
            if (connfd > maxfd)
                maxfd = connfd; /* select第一个参数需要 */

            /* 更新client[]最大下标值 */
            if (i > maxi)
                maxi = i;
            /* 
             * 如果没有更多的就绪文件描述符继续回到上面select阻塞监听,负责处理未
             * 处理完的就绪文件描述符 
             * */
            if (--nready == 0)
                continue;
        }

        bzero(buf, MAXLINE);
        for (i = 0; i <= maxi; i++)
        {  
            if ( (sockfd = client[i]) < 0)
                continue;

            if (FD_ISSET(sockfd, &rset))
            {  
                printf("config  updata\n");
                while ((n = read(sockfd, buf, MAXLINE)) > 0)
                {
                    printf("buf: %s\n", buf);

                    // 接收到数据之后解析 处理
                    Parse_config_update(buf, n);

                    bzero(buf, MAXLINE);
                }

                if ( n== 0 ) {
                    /* 当client关闭链接时,服务器端也关闭对应链接 */
                    close(sockfd);
                    FD_CLR(sockfd, &allset);
                    /* 解除select监控此文件描述符 */
                    client[i] = -1;
                }

                if (--nready == 0)
                    break;  // end for
            }  
        }  
    }
    return 0;
}
上一篇 下一篇

猜你喜欢

热点阅读