我正在使用 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()
的情况下删除 session ,如下所示:
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;
}
但程序在“Debug 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()
而不等待答案,然后用新客户端覆盖指针,不删除旧客户端。这将是一个非常不干净的解决方案。
我该怎么做才能关闭 session 并打开一个新 session ?
最佳答案
The only possibility I can see at this point is to call close() without waiting for the answer and then overwriting the pointer with a new client, leaving the old one undeleted. This would be a very unclean solution.
使用关闭处理程序可以进行一些清理:
#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++)。
关于c++ - 如何重新连接到不响应 close() 的服务器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38556545/