c++ - 如何重新连接到不响应 close() 的服务器

标签 c++ websocket casablanca

我正在使用 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/

相关文章:

C++我应该循环并设置一个数组还是手动设置所有以提高性能

c++ - C++中的简单链表

javascript - 将 ssl 与 websocket 一起使用时出错

c++ - 使用 C++ REST SDK (Casablanca) 的 Http_client post 请求

c++ - pplx::守护进程未执行的任务

c++ - 构造函数调用顺序与组合

c++ - 类似浮点函数的不同结果

websocket - 是什么导致Dart类 '_WebSocketImpl'中没有实例方法 'send'的错误?

websocket - 使用 Server-Sent 事件进行双向客户端-服务器通信(而不是 WebSockets)的缺点

c++ - 响应代码 302 的 CPPREST 重定向位置