gpt4 book ai didi

c - 在 if 语句 poll() block 中,每个请求触发函数多次

转载 作者:行者123 更新时间:2023-11-30 19:19:43 25 4
gpt4 key购买 nike

我尝试用 C 语言编写简单的服务器,它使用 poll() 来测试监听套接字中是否有传入请求,并创建一个线程来服务请求。在测试 fds[0].revents & POLLIN 的 if 语句 block 中,每个请求创建一个线程,但 printf 每个请求执行多次。

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/poll.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

struct sockaddr_in serverAddr, clientAddr;
struct pollfd fd[1];
socklen_t clientlen;
pthread_attr_t pattr;
int serverfd, optval = 1;

void *accreq(void *);
void make_request_thread();
void sig_handler(int);

int main(int argc, char *argv[])
{
signal(SIGINT, sig_handler);

serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(80);
inet_pton(AF_INET, "127.0.0.1", &serverAddr.sin_addr.s_addr);

serverfd = socket(AF_INET, SOCK_STREAM, 0);
setsockopt(serverfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
bind(serverfd, (struct sockaddr *)&serverAddr, sizeof(serverAddr));
listen(serverfd, 5);

clientlen = sizeof(clientAddr);

fd[0].fd = serverfd;
fd[0].events = POLLIN;

pthread_attr_init(&pattr);
pthread_attr_setdetachstate(&pattr, PTHREAD_CREATE_JOINABLE);

while(1)
{
if(poll(fd, 1, -1) > 0)
{
if(fd[0].revents & POLLIN)
{
printf("Hello!\n"); /* Why this function executed more than once per incoming request*/
make_request_thread();
}
}
}//end while loop

return 0;
}

void *accreq(void *arg)
{
int saccfd = accept(serverfd, (struct sockaddr *)&clientAddr, &clientlen), port, rc, wc;

char buffer[2048], addr[INET_ADDRSTRLEN];

inet_ntop(AF_INET, &clientAddr.sin_addr.s_addr, addr, INET_ADDRSTRLEN);
port = ntohs(clientAddr.sin_port);
printf("[Accept request from %s:%i]\n", addr, port);

rc = read(saccfd, buffer, sizeof(buffer));
printf("%s\n", buffer);
wc = write(saccfd, buffer, strlen(buffer));
close(saccfd);
pthread_exit(0);
}

void make_request_thread()
{
pthread_t thread_acc;
pthread_create(&thread_acc, &pattr, accreq, NULL);
}

void sig_handler(int signo)
{
printf("\nCatch signal interrupt\nExiting...\n");
pthread_attr_destroy(&pattr);
close(serverfd);
exit(0);
}

最佳答案

你有竞争条件。竞争发生在将在接受套接字上再次调用 poll() 的主线程与将在该套接字上调用 accept() 的生成线程之间。如果调用 accept() 的派生线程获胜,则主线程将阻塞(如果只有一个传入连接)。如果主线程获胜,poll() 调用将立即返回,因为套接字仍然有一个挂起的连接等待被接受。

在您的代码中,您根本不需要使用poll()。您可以简单地阻止对accept()的调用,并为生成的线程提供新创建的套接字来处理。如果您确实想要 poll(),最简单的解决方法是在 poll() 唤醒后在主线程中调用 accept(),然后将新创建的套接字提供给生成的线程。

关于c - 在 if 语句 poll() block 中,每个请求触发函数多次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23840347/

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