Как переподключиться к серверу, который не отвечает закрыть ()
Я использую C++ REST SDK
("Касабланка") для получения фида с серверов веб-сокетов.
Иногда мне нужно закрыть соединение и переподключиться. В библиотеке нет 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
здесь: ссылка:
~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()
не дожидаясь ответа, а затем перезаписывая указатель новым клиентом, оставляя старый не восстановленным. Это было бы очень нечистым решением.
Что я могу сделать, чтобы закрыть сеанс и открыть новый?
2 ответа
Я также столкнулся с этой проблемой, и причина, по которой у меня возникла проблема, была связана с моей попыткой очистить websocket_callback_client от обработчика закрытия. если я этого не сделаю, то кажется, что он изумительно очищается.
Единственная возможность, которую я вижу на данный момент, - это вызвать close(), не дожидаясь ответа, а затем перезаписав указатель новым клиентом, оставив старый не восстановленным. Это было бы очень нечистым решением.
Некоторая очистка может быть возможна с использованием обработчика закрытия:
#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++).