2016-07-24 5 views
0

Ich verwende die C++ REST SDK ("Casablanca"), um Feed von Websocket-Servern zu empfangen.Verbindung mit einem Server herstellen, der nicht auf Schließen antwortet()

Manchmal muss ich die Verbindung schließen und erneut verbinden. Die Bibliothek hat keine reconnect Funktion, also schließe ich die alte Verbindung und öffne einfach eine neue. Das Problem ist, dass der Server auf der anderen Seite, wie es scheint, nicht auf meine nahe Nachricht antwortet.

Dies ist der Code:

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; 
} 

Wie gesagt, scheint es, wie der Server close() nicht antwortet, so wird das Programm bei this->m_clClient.close().get(); für immer fest.

Ich habe auch versucht, die Sitzung zu löschen, ohne ein close() zu senden, etwa so:

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; 
} 

Aber das Programm noch nach dem "Debug 1" stecken bleibt. Ich denke, die close() wird im Destruktor websocket_callback_client aufgerufen, wenn es nicht zuvor getan wurde.

ich den Quellcode der Bibliothek gesucht und gefunden haben, die destructor von websocket_callback_client hier: 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; 
} 

Wie Sie unter case CLOSING: sehen wartet er auf die Verbindung zu schließen.

Die einzige Möglichkeit, die ich an dieser Stelle sehen kann, ist close() ohne Warten auf die Antwort und dann den Zeiger mit einem neuen Client überschreiben, so dass die alte gelöscht. Dies wäre eine sehr unreine Lösung.

Was kann ich tun, um die Sitzung zu schließen und eine neue zu öffnen?

Antwort

0

Die einzige Möglichkeit, die ich an dieser Stelle sehen kann, liegt in der Nähe() aufrufe ohne die Antwort abzuwarten und dann mit einem neuen Client die Zeiger zu überschreiben, undeleted die alten zu verlassen. Dies wäre eine sehr unsaubere Lösung.

Einige Bereinigung möglich sein könnte, eine enge Handler:

#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; 
}; 

Da der Code in der Frage gepostet kein komplettes Programm konnte ich nicht meine Lösung testen Ausnahme, dass es kompiliert (Klirren ++/g ++).

+0

Ich habe meine Frage bearbeitet und weitere Details hinzugefügt. Leider ist es nicht möglich, 'get()' wegzulassen, da der Destruktor immer noch darauf wartet. Die einzige Lösung wäre, 'close()' ohne 'get()' aufzurufen und dann den Zeiger zu überschreiben, wobei der alte Client nicht gelöscht wird. – Bobface

0

Ich stieß auch auf dieses Problem, und der Grund, warum ich das Problem hatte, war aufgrund meines Versuchs, den websocket_callback_client vom close-Handler zu bereinigen. wenn ich das nicht tue, scheint es sich wunderbar zu reinigen.

Verwandte Themen