2016-07-24 55 views
0

C++ REST SDK( "Casablanca")を使用してwebsocketサーバーからフィードを受信して​​います。close()に応答しないサーバーに再接続する

時には、接続を閉じて再接続する必要があります。ライブラリには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のデストラクタを発見した

link:あなたがcase CLOSING:の下で見ることができるように接続をクローズするため

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

は、それが待ちます。

この時点で私が見ることのできるのは、答えを待たずに新しいクライアントでポインタを上書きして、古いものを削除しないままでclose()に電話することだけです。これは非常に汚れた解決策になります。

セッションを閉じて新しいセッションを開くには、どうすればよいですか?私はこの時点で見ることができます

答えて

0

唯一の可能性は、未削除古いものを残して、返事を待って、その後 新しいクライアントとのポインタを上書きせずに )(近い呼び出すことです。これは非常に汚い解決策 になります。

いくつかのクリーンアップが近いハンドラ使用して実現できる:質問に投稿されたコードが、私はそれが(打ち鳴らす++/gでコンパイルされることを除いて私の解決策をテストすることができませんでした完全なプログラムではありませんので

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

を++ )。

+0

質問を編集して詳細を追加しました。残念ながら、デストラクタがまだそれを待つので、 'get()'を省略することはできません。唯一の解決策は、 'get()'を使わずに 'close()'を呼び出してポインタを上書きし、古いクライアントを削除しないままにすることです。 – Bobface

0

私もこの問題に遭遇しました。問題が発生したのは、closeハンドラからwebsocket_callback_clientをクリーンアップしようとしたためです。私がそれをしなければ、それは驚くほど自分自身をきれいにするようです。

関連する問題