gpt4 book ai didi

c - C 中的 Boss Worker Pthreads Web 服务器 - 如果发送的请求多于线程数,服务器会崩溃

转载 作者:太空狗 更新时间:2023-10-29 15:04:30 25 4
gpt4 key购买 nike

我正在使用 Pthreads(我更糟糕)用 C(我很糟糕)编写一个 Web 服务器,我被困在了这一点上。服务器的模型是 boss-worker,因此 boss 线程在程序开始时实例化所有工作线程。有一个全局队列存储传入连接的套接字。老板线程是在接受连接时将所有项目(套接字)添加到队列的线程。然后所有的工作线程等待一个项目被添加到一个全局队列中,以便它们开始处理。

只要我连接服务器的次数少于服务器拥有的工作线程数,服务器就可以正常工作。因此,我认为我的互斥量有问题(也许信号丢失了?)或者线程在运行一次后被禁用(这可以解释为什么如果有 8 个线程,它只能解析第一个8 个 http 请求)。

这是我的全局队列变量。

int queue[QUEUE_SIZE];

这是主线程。它使用入队、出队、空等方法创建一个队列结构(在别处定义)。当服务器接受连接时,它将传入连接所在的套接字入队。一开始调度的工作线程不断地检查这个队列,看看是否有任何作业被添加,如果有作业,它们就会使套接字出队,连接到那个端口,并读取/解析/写入传入的 http 请求.

int main(int argc, char* argv[])
{
int hSocket, hServerSocket; /* handle to socket */
struct hostent* pHostInfo; /* holds info about a machine */
struct sockaddr_in Address; /* Internet socket address stuct */
int nAddressSize = sizeof(struct sockaddr_in);
int nHostPort;
int numThreads;
int i;

init(&head,&tail);

//**********************************************
//ALL OF THIS JUST SETS UP SERVER (ADDR STRUCT,PORT,HOST INFO, ETC)
if(argc < 3) {
printf("\nserver-usage port-num num-thread\n");
return 0;
}
else {
nHostPort=atoi(argv[1]);
numThreads=atoi(argv[2]);
}

printf("\nStarting server");

printf("\nMaking socket");
/* make a socket */
hServerSocket=socket(AF_INET,SOCK_STREAM,0);

if(hServerSocket == SOCKET_ERROR)
{
printf("\nCould not make a socket\n");
return 0;
}

/* fill address struct */
Address.sin_addr.s_addr = INADDR_ANY;
Address.sin_port = htons(nHostPort);
Address.sin_family = AF_INET;

printf("\nBinding to port %d\n",nHostPort);

/* bind to a port */
if(bind(hServerSocket,(struct sockaddr*)&Address,sizeof(Address)) == SOCKET_ERROR) {
printf("\nCould not connect to host\n");
return 0;
}
/* get port number */
getsockname(hServerSocket, (struct sockaddr *) &Address,(socklen_t *)&nAddressSize);

printf("Opened socket as fd (%d) on port (%d) for stream i/o\n",hServerSocket, ntohs(Address.sin_port));

printf("Server\n\
sin_family = %d\n\
sin_addr.s_addr = %d\n\
sin_port = %d\n"
, Address.sin_family
, Address.sin_addr.s_addr
, ntohs(Address.sin_port)
);
//Up to this point is boring server set up stuff. I need help below this.
//**********************************************

//instantiate all threads
pthread_t tid[numThreads];

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

printf("\nMaking a listen queue of %d elements",QUEUE_SIZE);
/* establish listen queue */
if(listen(hServerSocket,QUEUE_SIZE) == SOCKET_ERROR) {
printf("\nCould not listen\n");
return 0;
}

while(1) {

pthread_mutex_lock(&mtx);
printf("\nWaiting for a connection");

while(!empty(head,tail)) {
pthread_cond_wait (&cond2, &mtx);
}

/* get the connected socket */
hSocket = accept(hServerSocket,(struct sockaddr*)&Address,(socklen_t *)&nAddressSize);

printf("\nGot a connection");

enqueue(queue,&tail,hSocket);

pthread_mutex_unlock(&mtx);
pthread_cond_signal(&cond); // wake worker thread
}
}

这里是工作线程。这应该始终运行检查新请求(通过查看队列是否为空)。在这个方法的最后,它应该推迟到老板线程等待下一次需要它。

void *worker(void *threadarg) {

pthread_mutex_lock(&mtx);

while(empty(head,tail)) {
pthread_cond_wait(&cond, &mtx);
}
int hSocket = dequeue(queue,&head);

unsigned nSendAmount, nRecvAmount;
char line[BUFFER_SIZE];

nRecvAmount = read(hSocket,line,sizeof line);
printf("\nReceived %s from client\n",line);


//***********************************************
//DO ALL HTTP PARSING (Removed for the sake of space; I can add it back if needed)
//***********************************************


nSendAmount = write(hSocket,allText,sizeof(allText));

if(nSendAmount != -1) {
totalBytesSent = totalBytesSent + nSendAmount;
}
printf("\nSending result: \"%s\" back to client\n",allText);

printf("\nClosing the socket");
/* close socket */
if(close(hSocket) == SOCKET_ERROR) {
printf("\nCould not close socket\n");
return 0;
}


pthread_mutex_unlock(&mtx);
pthread_cond_signal(&cond2);
}

如有任何帮助,我们将不胜感激。如果有人需要,我可以发布更多代码,请告诉我。我不是最擅长操作系统的东西,尤其是在 C 中,但我知道互斥锁、cond 的基础知识。变量,信号量等。就像我说的,我会尽我所能。 (另外,我不确定我发布的代码是否完全正确,因为这是我的第一个问题。如果我应该更改格式以使其更具可读性,请告诉我。)

谢谢!

最佳答案

worker 革命的时刻到了。

工作线程似乎缺少 while(true) 循环。在 HTTP 交换并关闭套接字之后,它们应该循环返回以在队列中等待更多套接字/请求。

关于c - C 中的 Boss Worker Pthreads Web 服务器 - 如果发送的请求多于线程数,服务器会崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12659093/

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