繁体   English   中英

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

[英]Creating a separate boost thread for endpoint.listen() in a multithreaded program using websocketpp library

我正在尝试将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服务器必须在其自己的线程中启动。

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

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

为什么要在堆上创建boost::thread时将其放在堆栈上?

您不需要将boost::bindboost::thread boost::bind使用,因此它应该很简单:

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

简单得多,不是吗?

至于您程序的行为。 如果您在其中调用ptr->join() ,那么主线程将等待另一个线程完成,这永远不会发生,因此它会休眠。 如果不加入,则ptrecho_endpoint以及h都超出范围。 然后另一个线程将尝试使用不再存在的对象。

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM