【发布时间】:2011-07-03 21:49:44
【问题描述】:
我正在设计一个带有线程池的多线程服务器。该系统旨在使用持久的 TCP 连接,因为客户端将保持接近 24/7 的连接。我遇到的问题是如何管理停机。目前,连接通过“accept(listen_fd ....)”进入并分配给工作订单结构。该结构被转储到工作队列中,并被线程拾取。从此时起,该线程专门用于当前连接。我在线程内的代码是:
/* Function which runs in a thread to handle a request */
void *
handle_req( void *in)
{
ssize_t n;
char read;
/* Convert the input to a workorder_ptr */
workorder_t *workorder_ptr = (workorder_t *)in;
while( !serv_shutdown
&& (n=recv(workorder_ptr->sock_fd,&read,1,0) != 0))
{
printf("Read a character: %c\n",read);
}
printf("Peer has shutdown.\n");
/* Free the workorder memory */
close(workorder_ptr->sock_fd);
free(workorder_ptr);
return NULL;
}
它只是监听套接字并无限期地回显字符,并在客户端终止连接时正确运行。您会在 while 循环中看到“!serv_shutdown”部分 - 这是我尝试让线程在关闭信号时脱离其循环。当捕获到 SIGINT 时,全局变量设置为 1。不幸的是,程序当前阻塞了 recv 语句,并且在读取另一个字符之前不会检查这个标志。我想避免这种情况,因为在此连接上发送另一个字符之前可能是任意时间。
另外,我在这里的另一篇文章中读到,最好使用“选择”而不是“接受”来等待套接字连接,但我不太明白。您会选择等待,然后立即接受吗?我不确定 select 如何创建套接字连接。我问这个,因为如果我对 select 的理解被清除了,也许它适用于我问的问题?
另外,我如何检测连接超时的情况?
谢谢!
编辑 经过进一步的挖掘,我想我可能终于找到了解决方案:
Wake up thread blocked on accept() call
基本上,我可以创建一个全局管道,并让每个线程在其自己的 socket_fd 以及这个全局管道上进行选择。然后,当捕获到信号时,我将向管道写入一些内容。所有线程都应该被唤醒,不是吗?
【问题讨论】: