C select() 出错

问题描述 投票:0回答:1

我制作了一个小型客户端/服务器程序,其中服务器可以使用

select()
函数同时处理多个客户端。当我运行我的程序时,一切正常,直到我杀死客户端程序,当我杀死客户端程序时,服务器不会在
select()
处阻塞,但它只是在 while 循环中迭代。

当我将

FD_SETSIZE
中的
select(FD_SETSIZE, &copyFds, NULL, NULL, NULL);
更改为
master_socket + 1
时,它不会阻塞,因此工作正常。

GNU 库说: select 函数仅检查第一个 nfds 文件描述符。通常的做法是传递 FD_SETSIZE 作为该参数的值。 https://www.gnu.org/software/libc/manual/html_node/Waiting-for-I_002fO.html

为什么我会遇到这个错误?如何传入

FD_SETSIZE
并且仍然让程序阻塞在
select()

服务器:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/time.h>

int main()
{
    system("clear");
    printf("***SERVER STARTED***\n");

    char message[125] = "Welcome to my server";
    int master_socket = socket(AF_INET, SOCK_STREAM, 0);
    fd_set masterFds, copyFds;

    struct sockaddr_in address;
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(8888);
    socklen_t addrlen = sizeof address;
    bind(master_socket, (struct sockaddr *)&address, sizeof(address));
    listen(master_socket, 1);

    FD_ZERO(&masterFds);
    FD_SET(master_socket, &masterFds);

    while (1)
    {
        copyFds = masterFds;

        printf("Monitoring for connections...\n");
        select(FD_SETSIZE, &copyFds, NULL, NULL, NULL); // When a socket wants to connect it's file descriptor gets stored in copyFds

        for (int i = 0; i < FD_SETSIZE; i++)
        {
            if (FD_ISSET(i, &copyFds))
            {
                if (i == master_socket) // New connection
                {
                    int accepted_socket = accept(master_socket, (struct sockaddr *)&address, &addrlen);
                    FD_SET(accepted_socket, &masterFds);
                    printf("[+] New connection accepted\n");

                    write(accepted_socket, message, sizeof(message)); // Send message to client
                }
                else
                {
                    // Not finished yet
                }
            }
        }

        printf("End of while loop\n");
    }
}

客户端(相同的标头):

int main()
{
    system("clear");
    int clientSocket = socket(AF_INET, SOCK_STREAM, 0), x;

    struct sockaddr_in serverAddress;
    serverAddress.sin_family = AF_INET;
    serverAddress.sin_port = htons(8888);
    serverAddress.sin_addr.s_addr = INADDR_ANY;

    connect(clientSocket, (struct sockaddr *)&serverAddress, sizeof(serverAddress));

    char serverResponse[125];
    read(clientSocket, serverResponse, sizeof(serverResponse));
    printf("test: %s\n", serverResponse);

    scanf("%d", &x);

    close(clientSocket);
}
c sockets posix-select
1个回答
1
投票

如果客户端关闭其连接,您需要从

select
正在监视的描述符集中删除该 fd。否则,它会立即返回,期待您对此采取一些行动
fd
。换句话说,添加如下内容:

char buf[1024];                                                            
ssize_t nr = read(i, buf, sizeof buf);                                     
switch( nr ){                                                              
case -1:                                                                   
        perror("read");                                                    
        /* fallthru */                                                     
case 0:                                                                    
        if( close(i) ){                                                    
                perror("close");                                           
        }                                                                  
        puts("Client connection closed");                                  
        FD_CLR(i, masterFds);                                              
        break;                                                             
default:                                                                   
        fwrite(buf, 1, nr, stdout);                                        
        fflush(stdout);                                                    
}

else
子句中。 (“尚未完成”部分。)

© www.soinside.com 2019 - 2024. All rights reserved.