使用select处理多个客户端请求会导致循环重启

时间:2017-03-23 01:22:58

标签: c sockets network-programming

这是我到目前为止的代码,我基本上有一个fd sock_comm,它是监听套接字,然后将建立并添加多个客户端套接字连接。我需要能够接受新连接,但也可以接收现有连接,因此我使用select。我在尝试迭代while循环意外重启的现有连接时遇到了问题。

int n = sock_comm+1;
int max_sock;
while (1) {
    max_sock = n;
    printf("sock_comm: %d\n", sock_comm);

    // Clear the fd_set and add back connections
    FD_ZERO(&readfds);
    for (int i=sock_comm; i < max_sock; i++) {
        FD_SET(i, &readfds);
    }
    select(n, &readfds, NULL, NULL, NULL);
    printf("max socket: %d\n", max_sock);
    fd = sock_comm;

    // Iterate through each connection
    while (fd < max_sock) {
        printf("fd: %d\n", fd);
        printf("sock_comm2: %d\n", sock_comm);

        // If activity on current connection
        if (FD_ISSET(fd, &readfds)) {
            printf("Connection on %d\n", fd);

            // If connection on listener, accept 
            if (fd == sock_comm) {
                if ((new_s = accept(sock_comm, (struct sockaddr *)&client_addr, &len)) < 1) {
                    perror("tcpserver: accept");
                    exit(1);
                }
                n++;
                client_info.sockid = new_s;
                // Join handler thread                                    
                pthread_create(&threads[0],NULL,join_handler,&client_info);
                pthread_join(threads[0],&exit_value);
                printf("sock_comm3: %d\n", sock_comm);
            } else {
                // Create and join thread for receiving data
            }
        }
        fd++;
        printf("sock_comm4: %d\n", sock_comm);
    }
 }

我希望初始连接后的输出是这样的:

sock_comm: 3
max socket: 4
fd: 3
sock_comm2: 3
Connection on 3
sock_comm3: 3
sock_comm4: 3
sock_comm: 3

然后选择过程再次开始。发生的事情是这样的:

sock_comm: 3
max socket: 4
fd: 3
sock_comm2: 3
Connection on 3
sock_comm3: 3
sock_comm4: 3
fd: 1
sock_comm2: 3
sock_comm4: 3
fd: 2
sock_comm2: 3
sock_comm4: 3
fd: 3
sock_comm2: 3
Connection on 3

正如您所看到的,while (fd < max_sock)循环正在重置,并以某种方式从1开始,但fd永远不应该低于3.我不知道我的代码有什么问题,它是否必须要做在循环中使用select?我之前从未使用它,但它导致奇怪的行为。当没有什么可以接受时,它会陷入接受状态。

加入处理程序:

void *join_handler(struct global_table *rec) {
        int newsock;
        struct packet packet_reg;
        newsock = rec->sockid;

        for (int i=0; i < REQUEST_NO; i++) {
                if (recv(newsock, &packet_reg, sizeof(packet_reg), 0) < 1) {
                        printf("Could not receive RG-%d\n", i+1);
                        exit(1);
                } else {
                        printf("Registered received: %s\n",packet_reg.data);
                }
        }

        // add to table
        pthread_mutex_lock(&my_mutex);
        counter++;
        record[counter].sockid = newsock;
        pthread_mutex_unlock(&my_mutex);

        // send response acknowledging registration
        packet_reg.type = htons(221);
        sprintf(packet_reg.data, "%d", newsock);
        if(send(newsock, &packet_reg, sizeof(packet_reg), 0) < 1) {
                printf("ACK send failed\n");
                exit(1);
        }
        pthread_exit(NULL);
}

0 个答案:

没有答案