Introducción al código fuente del servidor linux c select

 Mire directamente la parte del bucle while en la función principal que llama

Cada llamada a seleccionar cambiará el valor de FD_SET, por lo que se requieren dos variables, allset y un rset

Primero, vea si hay un cliente solicitando una conexión, y si hay una conexión para ser procesada.

Aquí usamos una matriz recién abierta para mantener los descriptores de archivos. La ventaja de esto es que si se usa una matriz dinámica, los descriptores de archivo se pueden mantener dinámicamente.

Recorra toda la matriz de clientes y luego vea si hay alguna información que se pueda leer

La desventaja de la función de selección es que FD_SET se copia en el área del núcleo cada vez, que es una multiplexación de E / S basada en el mecanismo de sondeo.

while (1) {   
        rset = allset;                                          /* 每次循环时都从新设置select监控信号集 */
        nready = select(maxfd+1, &rset, NULL, NULL, NULL);
        if (nready < 0)
            perr_exit("select error");
 
        if (FD_ISSET(listenfd, &rset)) {                        /* 说明有新的客户端链接请求 */
 
            clie_addr_len = sizeof(clie_addr);
            connfd = Accept(listenfd, (struct sockaddr *)&clie_addr, &clie_addr_len);       /* Accept 不会阻塞 */
            printf("received from %s at PORT %d\n",
                    inet_ntop(AF_INET, &clie_addr.sin_addr, str, sizeof(str)),
                    ntohs(clie_addr.sin_port));
 
            for (i = 0; i < FD_SETSIZE; i++)
                if (client[i] < 0) {                            /* 找client[]中没有使用的位置 */
                    client[i] = connfd;                         /* 保存accept返回的文件描述符到client[]里 */
                    break;
                }
 
            if (i == FD_SETSIZE) {                              /* 达到select能监控的文件个数上限 1024 */
                fputs("too many clients\n", stderr);
                exit(1);
            }
 
            FD_SET(connfd, &allset);                            /* 向监控文件描述符集合allset添加新的文件描述符connfd */
            if (connfd > maxfd)
                maxfd = connfd;                                 /* select第一个参数需要 */
 
            if (i > maxi)
                maxi = i;                                       /* 保证maxi存的总是client[]最后一个元素下标 */
 
            if (--nready == 0)
                continue;
        } 
 
        for (i = 0; i <= maxi; i++) {                               /* 检测哪个clients 有数据就绪 */
 
            if ((sockfd = client[i]) < 0)
                continue;
            if (FD_ISSET(sockfd, &rset)) {
 
                if ((n = Read(sockfd, buf, sizeof(buf))) == 0) {    /* 当client关闭链接时,服务器端也关闭对应链接 */
                    Close(sockfd);
                    FD_CLR(sockfd, &allset);                        /* 解除select对此文件描述符的监控 */
                    client[i] = -1;
                } else if (n > 0) {
                    for (j = 0; j < n; j++)
                        buf[j] = toupper(buf[j]);
                    Write(sockfd, buf, n);
                    Write(STDOUT_FILENO, buf, n);
                }
                if (--nready == 0)
                    break;                                          /* 跳出for, 但还在while中 */
            }
        }
    }

 

 

Supongo que te gusta

Origin blog.csdn.net/whatday/article/details/114257005
Recomendado
Clasificación