2011-02-24 59 views
1

我正在设计一个带线程池的多线程服务器。该系统旨在使用持久性TCP连接,因为客户端将维护24/7接近的连接。我碰到的问题是如何管理关机。目前,一个连接通过“accept(listen_fd ....)”进入,并被分配给工作订单结构。这个结构被转储到工作队列中,并被一个线程拾取。从这一点开始,这个线程专门用于当前的连接。我的线程里面的代码是:关闭持续TCP Con。 (C多线程服务器)

/* 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”而不是“accept”来等待套接字连接,但我不太明白。你会选择等待,然后在那之后做一个接受吗?我不确定select如何创建套接字连接。我问这个,因为如果我对select的理解被清除了,也许它适用于我所问的问题?

此外,如何检测连接超时的情况?

谢谢!

编辑 我想我可能终于找到了解决办法,经过进一步的挖掘:

Wake up thread blocked on accept() call

基本上,我可以创建一个全球性的管道,并让每个线程做一个选择对自己socket_fd以及这个全球管道。然后,当一个信号被捕获时,我只会写一些东西给管道。所有线程都应该醒来,不是?

回答

1

那么,在FreeBSD,MacOSX和其他地方有kevent()调用,它允许监听广泛的系统事件,包括数据到达套接字时连接请求和信号。它将以一种整洁的方式解决你所有的问题,但它不是可移植的。有libs这样的libevent和libev,它包含了OS特定的功能,如BSD的kevent(),Linux上的epoll()等等。可能会帮助你。