1

我正在尝试将 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 结果

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

4

2 回答 2

1

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

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

于 2012-07-16T15:04:31.837 回答
0

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

您不需要使用boost::bindwith boost::thread,所以它应该是简单的:

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

简单得多,不是吗?

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

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

从 Boost 1.50开始,如果线程在其析构函数运行时可连接,析构函数与ieboost::thread的行为相匹配。这是为了防止您遇到的那种错误,即使引用它的句柄和其他堆栈对象不再存在,线程也会继续运行。如果你想让它继续运行,你必须显式地运行它(但在你的程序中这仍然是错误的,因为and对象仍然会不复存在并且线程仍然会尝试使用它们。)所以在对象超出范围之前你应该要么它要么它。std::threadterminate()boost::threaddetachecho_endpointhboost::threadjoindetach

于 2012-07-16T15:34:46.630 回答