使用websocketpp库在多线程程序中为endpoint.listen()创建单独的boost线程

时间:2012-07-16 13:52:54

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

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

#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-&gt; join(); 编译代码,那么监听线程工作正常,但它会使主线程处于休眠状态。如果我离开 ptr-&gt; join()并让监听线程在后台运行,我在创建线程后遇到错误:

  

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

我对线程或增强线程不太熟悉,而且对于websocketpp来说还不是很新,所以我不确定我在这里做错了什么。如果有更好(和工作)的方法来解决这个问题,我很乐意看到一些例子。我一直试图找出这个问题很长一段时间,所以任何帮助都是无价的。提前致谢!

还可以退房:gdb stacktracevalgrind results

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

2 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:0)

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

您不需要将boost::bindboost::thread一起使用,因此应该只是:

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

更简单,不是吗?

关于你的程序的行为。如果你在那里调用ptr->join()那么主线程等待另一个线程完成,这从未发生过,所以它当然会睡觉。如果您不加入,则ptrecho_endpoint以及h都将超出范围。然后另一个线程将尝试使用不再存在的对象。

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

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