C ++中的多线程服务器,如何终止线程并很好地清理

时间:2014-07-18 08:28:56

标签: c++ multithreading sockets openssl thread-safety

我在c ++服务器上编写的服务器就像代理服务器一样。主要功能:

try
{
    Connector c(ip); //establishes persistent connection to the server B
    Listener1 l1(port); //listens incoming connection to the server A (our proxy) and push them into the queue
    Listener2 l2(&c); //listens responses (also push messages) from the server B and push them into the queue
    Proxy p(&c, &l1, &l2); //pulls clients  out from the queue and forwards requests to the server B, pull out everything from the listener2 queue and returns as a responce
    KeepAlive k(&l1, &p); //pushes the empty client to the listeners1's queue thus the proxy sends keepalive to the server B and the response is discarded
    l1.start();
    p.start();
    l2.start();
    k.start();
    l1.join();
    p.join();
    l2.join();
    k.join();
catch(std::string e)
{
    std::cerr << "Error: " << e << std::endl;
    return -1;
}

现在我有以下问题/怀疑:

** 1. **我从构造函数中抛出一个异常,这是一个好习惯吗?当无法建立连接时抛出异常,这就是为什么不应该创建对象的原因。

** 2. **关闭应用程序安全性并在发生连接超时或服务器B关闭连接等时出现问题。 listener1和listener2使用阻塞函数(系统调用accept()和来自openssl lib的BIO_read)因此不可能只从另一个线程设置循环条件。问题还在于所有模块都已连接并使用互斥锁共享资源。我当前的一段代码只是调用exit函数来终止整个应用程序。

我知道这不是一个完美的解决方案,我感谢任何建议和提示。

提前致谢

1 个答案:

答案 0 :(得分:2)

如果构造函数失败,它们应该抛出异常。 C ++旨在很好地处理这个问题。当且仅当它们已经构建时,基类和成员才被清理。

阻止其他库中的函数始终存在问题。 Windows和POSIX处理得很好:WSAWaitForMultipleObjectExselect允许您添加一个额外的句柄,您可以使用它来取消阻止等待。

accept调用中,您可以通过主线程通过localhost创建连接来伪装它。检测到这种“异常”连接将是一个停止接受进一步连接的信号。

对于openSSL读取,我只是从主线程中关闭套接字,threadafety是安全的。我会确保在关机后很晚才这样做,并且我不希望在此之后该库可以使用。