【问题标题】:Creating a job queue for a multi threaded server in C在 C 中为多线程服务器创建作业队列
【发布时间】:2026-01-03 23:45:02
【问题描述】:

我正在努力在 C 中设计一个多线程 Web 服务器 - 目标是拥有一个老板/工人模型,老板初始化队列、主套接字等,然后进入一个循环,它接受新的连接并入队新工作人员队列中的新套接字描述符。

!!!!编辑:我收到了一些有用的反馈,感觉我几乎可以实现链接列表了。但是我在这里仍然缺少一些东西。当我使用示例客户端运行服务器时,它不能正常工作(从不开始发送文件或显示输出)

要清楚,我有以下作为全局变量

 ptreads.h
 pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
 pthread_cond_t c_boss = PTHREAD_COND_INITIALIZER;
 pthread_cond_t c_worker = PTHREAD_COND_INITIALIZER;

队列结构:

//QUEUE STRUCTURE 
struct Node {
int data ;
struct Node * next;  // or link
};
struct Node* front = NULL;
struct Node* rear = NULL;

void Enqueue(int x){
           details
                }
void Dequeue(){
details
}

主要:

 ServerSocket = socket(AF_INET, SOCK_STREAM, 0);

  bzero(&server, sizeof(server));
  server.sin_family = AF_INET;
  server.sin_addr.s_addr = htonl(INADDR_ANY);
  server.sin_port = htons(HostPort);


bind(ServerSocket, (struct sockaddr *)&server, sizeof(server));

listen(ServerSocket, max_pending_connections)


 pthread_t tid[numThreads];
int i;
for(i = 0; i <numThreads; i++){
pthread_create(&tid[i], NULL, thread, NULL);
}

    while(1)

    while(front==NULL)
    {
    pthread_cond_wait (&c_boss, &mtx); 
    }

    pthread_mutex_lock(&mtx);

    enqueue(client_sock);

    pthread_mutex_unlock(&mtx);

    pthread_cond_signal(&c_worker);  

  }

最后是工作线程:

void *thread(void * ServerSocket)

int   peer_socket =  *(int *) ServerSocket; // copy the socket
{
while(1){
pthread_mutex_lock(&mtx);

while (front == NULL){
pthread_cond_wait(&c_worker, &mtx);}

peer_socket = Dequeue;

pthread_mutex_unlock(&mtx);

pthread_cond_signal(&c_worker);

DOES WORK 
close(fd);       // close the file
      close(peer_socket); // close the client connection

      pthread_exit(NULL);

【问题讨论】:

    标签: c multithreading sockets queue threadpool


    【解决方案1】:

    我认为链表 (FIFO) 队列效果最好?

    是的,双向链表适用于该应用程序。老板线程可以将项目附加到列表的尾部,而工作线程可以从列表的头部弹出项目。 (当然,在发生这些操作时,请确保在这两种情况下互斥锁都已锁定)

    您发布的代码在正确的轨道上;在老板线程中你不需要做(也不应该做)的一件事是在 pthread_cond_wait() 中阻塞。您的老板线程将在 accept(); 中阻塞。它没有必要(AFAIK)阻止等待队列变空。

    我认为您的工作线程函数中的 while 循环可以消失;像这样连续多次调用 pthread_cond_wait() 是没有意义的。相反,我会在该函数的全部内容周围放置一个 while(1) 循环,这样一旦线程完成其在此处的工作,它就可以立即返回等待队列中的下一个作业。 (使用完后不要忘记 close() peer_socket)

    【讨论】:

    • 您应该始终在循环中调用 pthread_cond_wait(),代码是正确的。谷歌“虚假唤醒”
    • 我认为这是在“WORK HERE”部分周围放置“if (peer_socket != NULL)”的好理由;但是仍然不需要围绕 pthread_cond_wait() 调用进行循环,因为外部 while(1) 循环会正确处理虚假唤醒。
    • 非常感谢您的反馈 - 我添加了一个编辑,因为我仍然有一些严重的队列问题,非常感谢任何帮助
    • Enqueue() 似乎试图将节点添加到列表中的第二个位置,而不是列表的末尾。 Enqueue() 从不设置 newNode->tail; Dequeue() 永远不会取消设置 head->prev.
    最近更新 更多