关闭持久TCP协议(C多线程服务器)

时间:2011-02-24 21:43:48

标签: sockets pthreads

我正在设计一个带线程池的多线程服务器。该系统旨在使用持久性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”而不是“accept”等待套接字连接,但我不太明白。你会选择等待,然后在那之后做一个接受吗?我不确定select如何创建套接字连接。我问这个,因为如果我对选择的理解被澄清了,那么它可能适用于我要问的问题吗?

另外,我如何检测连接只是超时的情况?

谢谢!

修改 我想在进一步挖掘后我可能终于找到了解决方案:

Wake up thread blocked on accept() call

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

2 个答案:

答案 0 :(得分:1)

好吧,在FreeBSD,MacOSX和其他地方都有kevent()调用,它允许监听广泛的系统事件,包括连接请求和数据到达套接字时的信令。 它将以一种简洁的方式解决您的所有问题,但它不可移植。有一些libs,例如libevent和libev,它们包含特定于操作系统的功能,如BSD上的kevent(),Linux上的epoll()等等。可能会帮助你。

答案 1 :(得分:1)

您可以使用recv()原语。如果它返回0,则表示套接字已关闭。

更多信息:http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html#recvman