gpt4 book ai didi

C - accept() 接受同一个客户两次?

转载 作者:太空宇宙 更新时间:2023-11-04 02:49:30 25 4
gpt4 key购买 nike

我正面临着我生命中最奇怪的编程问题之一。我以前搭建过几台服务器,客户端可以正常连接,没有任何问题。

现在我正在创建一个基本上是网络服务器的服务器。但是,我面临着一个非常奇怪的情况(至少对我而言)。

假设您连接到 localhost:8080 并且 accept() 接受您的连接,然后代码将在一个单独的线程中处理您的请求(这个想法是在每个子进程中有多个分支和线程 - 这是在另一个文件上实现的暂时但我在该设置上也面临这个问题所以......最好先让它简单)。因此,您的请求得到了处理,但是在处理完并且套接字被关闭之后,您在浏览器上看到了输出,accept() 再次接受了一个连接——但是当然没有人连接,因为只创建了一个连接。

errno = 0(成功)在 recv 之后(程序崩溃的地方)尽管 recv 返回 0 - 所以没有读取字节(当然,因为连接不应该存在)

int main(int argc, char * argv[]){
int sock;
int fd_list[2];
int fork_id;

/* Socket */
sock=create_socket(PORT);

int i, active_n=0;
pthread_t tvec;
char address[BUFFSIZE];
thread_buffer t_buffer;
int msgsock;

conf = read_config("./www.config");
if(conf == NULL)
{
conf = (config*)malloc(sizeof(config));
if(conf == NULL)
{
perror("\nError allocating configuration:");
exit(-1);
}

// Set defaults
sprintf(conf->httpdocs, DOCUMENT_ROOT);
sprintf(conf->cgibin, CGI_ROOT);
}

while(cicle) {

printf("\tWaiting for connections\n");
// Waits for a client
msgsock = wait_connection(sock, address);
printf("\nSocket: %d\n", msgsock);

t_buffer.msg = &address;
t_buffer.sock = msgsock;
t_buffer.conf = conf;

/* Send socket to thread */

if (pthread_create(&tvec, NULL, thread_func, (void*)&t_buffer) != 0)
{
perror("Error creating thread: ");
exit(-1);

}
}

free(conf);

return 0;
}

这里使用了两个重要的函数:

int create_socket(int port) {
struct sockaddr_in server, remote;
char buffer[BUFF];
int sock;

sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
perror("opening stream socket");
exit(1);
}

server.sin_family = AF_INET;
server.sin_port = htons(port);
server.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(sock, (struct sockaddr *) &server, sizeof(struct sockaddr_in))) {
perror("binding stream socket");
exit(1);
}
gethostname(buffer, BUFF);
printf("\n\tServidor a espera de ligações.\n");
printf("\tUse o endereço %s:%d\n\n", buffer,port);

if (listen(sock, MAXPENDING) < 0) {
perror("Impossível criar o socket. O servidor vai sair.\n");
exit(1);
}
return(sock);
}

int wait_connection(int serversock, char *remote_address){
int clientlen;
int clientsock;

struct sockaddr_in echoclient;

clientlen = sizeof(echoclient);
/* Wait for client connection */
if ((clientsock = accept(serversock, (struct sockaddr *) &echoclient, &clientlen)) < 0)
{
perror("Impossivel estabelecer ligacao ao cliente. O servidor vai sair.\n");
exit(-1);
}

printf("\n11111111111111Received request - %d\n", clientsock);

sprintf(remote_address, "%s", inet_ntoa(echoclient.sin_addr));

return clientsock;
}

所以基本上你会看到:11111111111111收到请求-D

D 两次都不同,所以 fd 肯定不同。

两次!一个接一个地处理完,然后在线程函数中接收到 recv 后爆炸。有时需要一点时间才能处理和显示第二个,但它会在几秒钟后完成。现在,这并不总是发生。有时会,有时不会。

这太奇怪了......

我已经推出了作为插件导致它重新连接或其他原因的可能性,因为 Apache 的 ab 工具在几次请求后导致了同样的问题。

我想指出,即使我不为客户端运行线程并简单地关闭套接字,它也会发生!我考虑过 header 未被完全读取的可能性,因此浏览器发送了另一个请求。但是浏览器会正确地接收回数据,否则它不会正常显示结果,如果它显示结果正常,则连接必须关闭良好 - 否则应该出现连接重置。

有什么建议吗?感谢您的帮助。

编辑:如果我取出代码的启动线程部分,有时连接会被接受 4、5、6 次...

编辑 2:请注意,我知道程序在 recv 失败后崩溃,我是故意退出的。

最佳答案

这肯定是一个等待发生的错误:

  pthread_create(&tvec, NULL, thread_func, (void*)&t_buffer

您将局部变量 t_buffer 传递给您的线程。下次您接受客户时,可能会发生这种情况在另一个客户端完成之前,您也会将相同的变量传递给该线程,从而导致很多非常不确定的行为。(例如,2 个线程从同一连接读取,描述符上的双 close() 和其他奇怪现象。)

不是将相同的局部变量传递给每个线程,而是为每个新客户端动态分配一个新的 t_buffer

关于C - accept() 接受同一个客户两次?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23689025/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com