我正在尝试将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 stacktrace和valgrind results
修改 代码示例中的“while(true)”仅用于模拟主线程中的处理。我正在将一个websocket服务器集成到一个大型项目中,该项目具有在后台运行的不同类型的套接字连接,事件,数据处理,客户端同步等。 websocket连接提供了另一种使用Web客户端而不是本机客户端连接到服务器的方法。主线程创建了所有必要的东西,但我不能真正影响它们的创建顺序,因此必须在自己的线程中启动websocket服务器。
答案 0 :(得分:1)
您可以在try / catch范围内创建所有对象。离开此范围时,这些对象将被销毁。
因此,要么将对象定义移出try / catch,要么将while(true)
循环移入其中。
答案 1 :(得分:0)
为什么在堆上创建boost::thread
时,它可能在堆栈上?
您不需要将boost::bind
与boost::thread
一起使用,因此应该只是:
boost::thread t(f, &echo_endpoint, port, 1);
更简单,不是吗?
关于你的程序的行为。如果你在那里调用ptr->join()
那么主线程等待另一个线程完成,这从未发生过,所以它当然会睡觉。如果您不加入,则ptr
和echo_endpoint
以及h
都将超出范围。然后另一个线程将尝试使用不再存在的对象。
作为@IgorR。 said,你应该将while
循环放在try-catch块中,这样主循环中的工作可以在之前发生另一个线程及其使用的对象出去范围。
从Boost 1.50开始,boost::thread
析构函数匹配std::thread
的行为,即如果线程在其析构函数运行时可以连接,则它会调用terminate()
。这是为了防止你所遇到的那种错误,即使引用它的boost::thread
句柄和其他堆栈对象不再存在,线程仍继续运行。如果你希望它继续运行,你必须明确地detach
它(但在你的程序中仍然是错误的,因为echo_endpoint
和h
对象仍然不复存在而且线程会仍然尝试使用它们。)因此,在boost::thread
对象超出范围之前,您应该join
它或detach
它。