应用层如何管理 websocketpp 的连接句柄 (connection hdl)?

in #cn-programming6 years ago

用过 websocketpp 的同学都知道, 应用程序需要自己保存各个客户端的连接句柄, 这个动作一般是在连接打开后, 在 on_open 回调中将句柄加入自己的容器中, 然后在 on_close 回调中将句柄移除. 问题就在于这里选用什么容器.

一开始会想这还不简单, 无非就是 vector, set, map 嘛, connection hdl 这种东西用 vector 就行了!

这里用 vector 的话, 添加句柄没问题, 然而移除句柄却并没有想象的那么直接, 最初我在 on_close 中是这样写的:

void rpcd::on_close(websocket_asio_server* s, websocketpp::connection_hdl hdl) {
  conn_hdls.erase(std::remove(std::begin(conn_hdls), std::end(conn_hdls), hdl));
}

结果显然, 连编译都过不了, 原因是 vector 要移除数据得先靠比较操作找到值相同的元素, 获得其迭代器交给 erase 去移除. 然而 websocketpp::connection_hdl 是个 weak_ptr, 就没定义比较操作运算符, 所以无法比较.

所以这里得自己定义比较方式, 我们知道通过 weak_ptr.lock() 可以获得它所共享的 shared_ptr 的值, 那上面代码就可以改成这样了:

void rpcd::on_close(websocket_asio_server* s, websocketpp::connection_hdl hdl) {
  conn_hdls.erase(std::remove_if(std::begin(conn_hdls), std::end(conn_hdls),
                                 [&](const websocketpp::connection_hdl& a) {
                                   if (a.lock() == hdl.lock()) return true;
                                   return false;
                                 }));
}

这里有个小细节是当连接断开时, connection_hdl 会被释放, 届时 a.lock() 会返回 nullptr. 但是经过验证证明在 on_close 时是还没有释放的, 而且就算释放了, 对这段代码也没有影响.

Coin Marketplace

STEEM 0.19
TRX 0.15
JST 0.029
BTC 63219.83
ETH 2574.36
USDT 1.00
SBD 2.78