【问题标题】:Creating a separate boost thread for endpoint.listen() in a multithreaded program using websocketpp library使用 websocketpp 库在多线程程序中为 endpoint.listen() 创建单独的 boost 线程
【发布时间】:2012-07-16 13:52:53
【问题描述】:

我正在尝试将 websocketpp 服务器集成到多线程项目中。在单线程方法中一切正常,但是在为将在后台运行的 endpoint.listen() 创建单独的 boost::thread 时遇到了问题(因此它不会中断主线程的执行)。我已经在具有最新版本的 websocketpp 的 Ubuntu 12.04 64 位上尝试了 Boost v1.46.1 和 v1.50.0 的代码。下面是一个代码示例和我的方法的解释。

#include <websocketpp/websocketpp.hpp>
#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include <exception>

using websocketpp::server;

class echo_server_handler : public server::handler {
public:
    void on_message(connection_ptr con, message_ptr msg) {
        con->send(msg->get_payload(),msg->get_opcode());
    std::cout << "Got message: " << msg->get_payload() << std::endl;
    }
};


int main(int argc, char* argv[]) {

    unsigned short port = 9002;

    try {       
        server::handler::ptr h(new echo_server_handler());
        server echo_endpoint(h);

        echo_endpoint.alog().unset_level(websocketpp::log::alevel::ALL);
        echo_endpoint.elog().unset_level(websocketpp::log::elevel::ALL);

        echo_endpoint.alog().set_level(websocketpp::log::alevel::CONNECT);
        echo_endpoint.alog().set_level(websocketpp::log::alevel::DISCONNECT);

        echo_endpoint.elog().set_level(websocketpp::log::elevel::RERROR);
        echo_endpoint.elog().set_level(websocketpp::log::elevel::FATAL);

        std::cout << "Starting WebSocket echo server on port " << port << std::endl;

        //Getting pointer to the right function
         void(websocketpp::role::server<websocketpp::server>::*f)(uint16_t,size_t) =
                &websocketpp::role::server<websocketpp::server>::listen;

        std::cout << "Starting WSServer thread... \n" << std:endl;
        boost::shared_ptr<boost::thread> ptr(new boost::thread(boost::bind(f, &echo_endpoint, port, 1)));
    //ptr->join();

    } catch (std::exception& e) {
        std::cerr << "Exception: " << e.what() << std::endl;
    }

    //Simulating processing in the main thread
    while(true) {std::cout << "Main thread processing..."<<std::endl; sleep(5);}


    return 0;

}

如果我用 ptr->join(); 编译代码,监听线程工作正常,但它会使主线程休眠。如果我离开 ptr->join() 并让监听线程在后台运行,我会在线程创建后遇到错误:

/usr/local/boost_1_50_0/libbin/include/boost/thread/pthread/recursive_mutex.hpp:105: void boost::recursive_mutex::lock(): 断言 `!pthread_mutex_lock(&m)' 失败。

我对线程或提升线程不是很有经验,而且对 websocketpp 还是很陌生,所以我不确定我是否在这里做错了什么。如果有更好的(和有效的)方法来解决这个问题,我很乐意看到一些例子。我一直在努力解决这个问题很长时间,所以任何帮助都是无价的。提前致谢!

也请查看:gdb stacktracevalgrind results

编辑: 代码示例中的“while(true)”只是为了模拟主线程中的处理。我正在一个大型项目中集成一个 websocket 服务器,该项目在后台运行不同类型的套接字连接、事件、数据处理、客户端同步等。 websocket 连接提供了另一种使用 Web 客户端而不是本机客户端连接到服务器的方法。主线程创建所有必要的东西,但我不能真正影响它们的创建顺序,所以 websocket 服务器必须在它自己的线程中启动。

【问题讨论】:

  • 您可以找到 websocketpp 示例 here 或在您的 websocketpp 副本的示例文件夹中。
  • 我已经尝试了所有的例子。我的代码示例是 echo_server 示例的修改版本。
  • 还有另一个例子 - concurrent server。它演示了如何创建多线程服务器。
  • 如果没有ptr-&gt;join,服务器及其处理程序将在离开try-catch 范围后被销毁。这就是为什么会有断言。
  • 如果我理解正确的话,在并发服务器示例中,会启动一个单独的线程来处理每个请求。但是,等待和处理连接的套接字侦听器仍然会停止主线程,从而阻止主线程中的任何并发处理。

标签: c++ multithreading boost websocket boost-thread


【解决方案1】:

您在 try/catch 范围内创建所有对象。当您离开此范围时,这些对象将被销毁。

因此,要么将对象定义移出 try/catch,要么将 while(true) 循环移入其中。

【讨论】:

  • 感谢您的提示。明天我会进一步研究,如果我能正常工作或有更多问题,我会报告。
【解决方案2】:

你为什么要在堆上创建boost::thread,而它可能在堆栈上?

您不需要将boost::bindboost::thread 一起使用,所以应该很简单:

    boost::thread t(f, &echo_endpoint, port, 1);

简单多了,不是吗?

至于你的程序的行为。如果你在那里调用ptr-&gt;join(),那么主线程会等待另一个线程完成,这永远不会发生,所以它当然会休眠。如果你不加入它,那么 ptrecho_endpointh 都会超出范围。然后另一个线程将尝试使用不再存在的对象。

作为@IgorR。 said,您应该将 while 循环放在 try-catch 块中,这样主循环中的工作就可以在其他线程及其使用的对象超出范围之前发生

从 Boost 1.50 开始,boost::thread 析构函数匹配 std::thread 的行为,即如果线程在其析构函数运行时可连接,它会调用 terminate()。这是为了防止您遇到的那种错误,即使引用它的boost::thread 句柄和其他堆栈对象不再存在,线程也会继续运行。如果您希望它继续运行,您必须明确地detach 它(但在您的程序中仍然是错误的,因为echo_endpointh 对象仍将不复存在并且线程仍将尝试使用它们。 ) 所以在 boost::thread 对象超出范围之前,您应该 join 它或 detach 它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-11-11
    • 2014-04-25
    • 2022-12-08
    • 2015-03-28
    • 1970-01-01
    • 2011-05-04
    • 2012-12-27
    • 1970-01-01
    相关资源
    最近更新 更多