我修改了websocket++ 回显服务器示例以使用多个线程:
#include <iostream>
#include <boost/thread/thread.hpp>
#include <websocketpp/config/asio_no_tls.hpp>
#include <websocketpp/server.hpp>
typedef websocketpp::server<websocketpp::config::asio> server;
using websocketpp::lib::placeholders::_1;
using websocketpp::lib::placeholders::_2;
using websocketpp::lib::bind;
// pull out the type of messages sent by our config
typedef server::message_ptr message_ptr;
// Define a callback to handle incoming messages
void on_message(server* s, websocketpp::connection_hdl hdl, message_ptr msg)
{
try {
s->send(hdl, msg->get_payload(), msg->get_opcode());
} catch (const websocketpp::lib::error_code& e) {
std::cout << "Echo failed because: " << e << "(" << e.message() << ")" << std::endl;
}
}
int main()
{
// Create a server endpoint
server echo_server;
boost::asio::io_service io_service;
try {
// Initialize Asio
echo_server.init_asio(&io_service);
// Register our message handler
echo_server.set_message_handler(bind(&on_message, &echo_server, ::_1, ::_2));
// Listen on port 9002
echo_server.set_reuse_addr(true);
echo_server.listen(9002);
// Start the server accept loop
echo_server.start_accept();
boost::thread_group threadpool;
threadpool.create_thread(boost::bind(&boost::asio::io_service::run, &io_service));
threadpool.create_thread(boost::bind(&boost::asio::io_service::run, &io_service));
threadpool.join_all();
} catch (websocketpp::exception const& e) {
std::cout << e.what() << std::endl;
} catch (...) {
std::cout << "other exception" << std::endl;
}
}
我使用一个异步发送许多消息的客户端进行连接。然后服务器崩溃:
2016-08-31 13:05:44] [info] asio async_read_at_least error: system:125 (Operation canceled)
[2016-08-31 13:05:44] [error] handle_read_frame error: websocketpp.transport:2 (Underlying Transport Error)
terminate called after throwing an instance of 'std::bad_weak_ptr'
what(): bad_weak_ptr
从Thread Safety 上的 websocket++ 手册来看,我所做的应该是线程安全的:
Asio 传输为端点提供完整的线程安全性。使用 io_service 线程池,其中多个线程正在调用 io_service.run();
...
所有核心传输都保证给定连接的处理程序将被序列化。当传输和并发策略支持端点并发时,任何涉及 connection_hdl 的东西都应该是线程安全的。ie 可以安全地将connection_hdls 传递给其他线程,无限期地存储它们,并随时从任何线程调用将它们作为参数的端点方法。
我在这里想念什么?
我使用的客户端是基于 NodeJS 的:
客户端.js
var port = 9002;
var times = 10000;
var WebSocket = require("ws");
var ws = new WebSocket("ws://localhost:" + port);
ws.on('open', function open() {
for(var i = 0; i < times; ++i) {
ws.send(i);
}
});
通过以下方式开始:
$ npm install --save ws
$ node client.js