在C中为多线程服务器创建作业队列

时间:2015-02-06 02:04:03

标签: c multithreading sockets queue threadpool

我正在设计一个C-goal中的多线程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);

1 个答案:

答案 0 :(得分:0)

  

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

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

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

我认为你的worker-thread函数中的while循环可以消失;在这样的行中多次调用pthread_cond_wait()是没有意义的。相反,我会在该函数的整个内容周围放置一个while(1)循环,这样一旦线程完成它在这里工作,它就可以回到等待队列中的下一个作业。 (当你完成使用它时,不要忘记关闭()peer_socket)