我试图用C语言编写简单的服务器,该服务器使用poll()来测试侦听套接字中是否有传入请求,并创建一个线程来处理请求。在测试fds[0].revents & POLLIN
的if语句块中,每个请求创建一个线程,但是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()
,最简单的解决方法是在accept()
唤醒后在主线程中调用poll()
,并将新创建的套接字分配给生成的线程。
关于c - 在if语句poll()块中,每个请求触发多次函数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/23840347/