我试图用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/

10-14 22:10