1

(「カサブランカ」) を使用して、C++ REST SDKwebsocket サーバーからフィードを受信して​​います。

場合によっては、接続を閉じて再接続する必要があります。ライブラリには機能がない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;
}

しかし、プログラムは「Debug 1」の後でもスタックします。以前に行われていない場合close()は、のデストラクタで呼び出されると思います。websocket_callback_client

ライブラリのソース コードを検索したところ、websocket_callback_clienthere: 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()、応答を待たずに呼び出し、新しいクライアントでポインターを上書きし、古いクライアントを削除しないままにすることです。これは非常に不潔な解決策になります。

セッションを閉じて新しいセッションを開くにはどうすればよいですか?

4

2 に答える 2

1

この時点で確認できる唯一の可能性は、応答を待たずに 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 ++)。

于 2016-07-24T22:19:56.893 に答える