Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用select处理多个客户端请求会导致循环重新启动_C_Sockets_Network Programming - Fatal编程技术网

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

使用select处理多个客户端请求会导致循环重新启动,c,sockets,network-programming,C,Sockets,Network Programming,这是我到目前为止的代码,我基本上有一个fdsock\u comm,它是监听套接字,然后将建立并添加多个客户端套接字连接。我需要能够接受新的连接,但也能够接收现有的连接,因此我使用select。我在尝试遍历while循环意外重新启动的现有连接时遇到了一个问题 int n = sock_comm+1; int max_sock; while (1) { max_sock = n; printf("sock_comm: %d\n", sock_comm); // Clear

这是我到目前为止的代码,我基本上有一个fd
sock\u 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
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
循环正在重置,不知何故从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);
}
void*join\u处理程序(结构全局表*rec){
国际新闻股;
结构数据包\u reg;
newsock=rec->sockid;
对于(int i=0;i
在这样的循环中调用
select()
是正常的。我在你发布的代码中没有看到任何东西可以设置
fd
小于
sock\u comm
。可能在覆盖变量的另一个线程中有错误的代码?如果将变量
fd
设置为
本地,而(1)
循环,会发生什么情况?另一个线程只处理本地变量,并使用新套接字发送确认。将
fd
本地设置为
,而(1)
则会明显改变行为。现在我在新的
fd
上的
recv
中得到了一个神秘的结果,当没有从客户端发送数据包时,它是通过accept创建的。
readfds
中只有
sock\u comm
。因此,您的
recv
将永远不会执行[并且您不想在那里使用
recv
]。您不显示thread funct,但希望让
main
do
accept
并将结果传递给
pthread\u create
,然后让函数do
recv
。此外,您还需要比立即
pthread\u连接更好的方法。您可能希望线程func独立运行,以便获得并行性。请注意,如果您需要传递
client\u info
,则必须
malloc
one[线程func执行
free
],否则您将获得竞态条件。或者,只要使用
(void*)new\u s
我不太清楚,如果要为每个客户端创建线程,为什么要使用
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);
}