如何重新连接到不响应 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-&gt;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() 的服务器的主要内容,如果未能解决你的问题,请参考以下文章

远程服务器无反应应如何处理

关闭连接后如何重新连接到websocket [重复]

无法连接到远程服务器 wcf服务

iOS:客户端如何重新连接到 xmpp 服务器

重新连接到服务器时如何强制 Atmosphere.js 使用首选传输?

尽管用户未连接到服务器,但用户仍处于联机状态。并且无法重新连接到服务器