如何重新连接到不响应 close() 的服务器
Posted
技术标签:
【中文标题】如何重新连接到不响应 close() 的服务器【英文标题】:Howto reconnect to a server which does not answer to close() 【发布时间】:2016-07-24 20:35:54 【问题描述】:我正在使用C++ REST SDK
(“Casablanca”)接收来自 websocket 服务器的提要。
有时,我需要关闭连接并重新连接。该库没有reconnect
函数,因此我关闭了旧连接并简单地打开一个新连接。问题在于,另一端的服务器似乎没有回复我的关闭消息。
这是代码:
web::websockets::client::websocket_callback_client* m_clClient;
///...
void Connection::reconnect()
std::cout << "Debug 1" << std::endl;
this->m_clClient.close().get();
delete this->m_clClient;
this->m_clClient = new web::websockets::client::websocket_callback_client();
std::cout << "Debug2" << std::endl;
正如我所说,服务器似乎没有回复close()
,因此程序永远卡在this->m_clClient.close().get();
。
我还尝试在不发送close()
的情况下删除会话,如下所示:
web::websockets::client::websocket_callback_client* m_clClient;
///...
void Connection::reconnect()
std::cout << "Debug 1" << std::endl;
delete this->m_clClient;
this->m_clClient = new web::websockets::client::websocket_callback_client();
std::cout << "Debug2" << std::endl;
但程序在“调试 1”之后仍然卡住。我认为 close()
是在 websocket_callback_client
的析构函数中调用的,如果之前没有这样做的话。
我搜索了库的源代码,发现websocket_callback_client
的析构函数在这里:link:
~wspp_callback_client()
_ASSERTE(m_state < DESTROYED);
std::unique_lock<std::mutex> lock(m_wspp_client_lock);
// Now, what states could we be in?
switch (m_state)
case DESTROYED:
// This should be impossible
std::abort();
case CREATED:
lock.unlock();
break;
case CLOSED:
case CONNECTING:
case CONNECTED:
case CLOSING:
// Unlock the mutex so connect/close can use it.
lock.unlock();
try
// This will do nothing in the already-connected case
pplx::task<void>(m_connect_tce).get();
catch (...)
try
// This will do nothing in the already-closing case
close().wait();
catch (...)
break;
// At this point, there should be no more references to me.
m_state = DESTROYED;
正如您在case CLOSING:
下看到的,它等待连接关闭。
此时我能看到的唯一可能性是调用close()
而不等待答案,然后用新客户端覆盖指针,保持旧客户端不被删除。这将是一个非常不干净的解决方案。
如何关闭会话并打开一个新会话?
【问题讨论】:
【参考方案1】:此时我能看到的唯一可能性是调用 close() 无需等待答案,然后用 a 覆盖指针 新客户,不删除旧客户。这将是一个非常 不干净的解决方案。
可以使用关闭处理程序进行一些清理:
#include <functional>
#include <unordered_set>
#include <cpprest/ws_client.h>
using namespace std::placeholders;
using namespace web::websockets::client;
typedef std::unordered_set<websocket_callback_client *> client_list;
class Connection
public:
Connection() : clients()
create_client();
void reconnect()
create_client();
// connect
void close_handler(websocket_callback_client * client,
websocket_close_status status,
const utility::string_t & reason,
const std::error_code & ec)
// check status and/or ec first?
clients.erase(client);
delete client;
// perform automatic reconnect if some flag tells so?
protected:
void create_client()
client = new websocket_callback_client();
clients.insert(client);
client->set_close_handler(std::bind(&Connection::close_handler, this,
client, _1, _2, _3));
websocket_callback_client * client;
client_list clients;
;
由于问题中发布的代码不是一个完整的程序,我无法测试我的解决方案,除非它可以编译(clang++ / g++)。
【讨论】:
我已经编辑了我的问题并添加了更多详细信息。不幸的是,忽略get()
是行不通的,因为析构函数仍会等待它。唯一的解决方案是在没有get()
的情况下调用close()
,然后覆盖指针,不删除旧客户端。【参考方案2】:
我也遇到了这个问题,我遇到问题的原因是我试图从关闭处理程序中清理 websocket_callback_client。如果我不这样做,它似乎会自动清理干净。
【讨论】:
以上是关于如何重新连接到不响应 close() 的服务器的主要内容,如果未能解决你的问题,请参考以下文章