Как принудительно отключить подключение к веб-сокету, если подключение к Интернету потеряно? - PullRequest
0 голосов
/ 05 апреля 2019

Я использую v0.14 из uWebsockets для создания клиента websocket, который взаимодействует с сервером websocket.Раздражающее поведение, которое я обнаружил в клиенте websocket, заключается в том, что при потере интернет-соединения (я отключаю компьютер от интернета напрямую для тестирования), клиент websocket не осознает этого и не вызывает ни onDisconnection, ни onError.После некоторого поиска в Google, я понял, что это ожидаемое поведение , и мне пришлось вручную настроить механизм ping-pong, чтобы клиент websocket быстро реагировал на потерянное соединение.Я реализовал механизм ping-pong, как было предложено, и теперь, когда мой клиент не может вовремя получить сообщение pong, он успешно завершает работу клиента и вызывается обратный вызов onDisconnection.Но поведение по-прежнему странное: при нормальном отключении (например, при постепенном отключении сервера) функция h.run возвращается после завершения onDisconnection.Однако в случае потери соединения h.run никогда не возвращается даже после завершения onDisconnection, и приложение просто зависает там.

Мой вопрос: может ли кто-нибудь, знакомый с uWebSockets, объяснить, как обрабатывать потерянное соединение, такчто клиент может быстро повторить попытку подключения к серверу?Любое предложение приветствуется.Было бы также полезно использовать решение с использованием других библиотек (или даже другого языка).

Ниже приведен неработающий код, который у меня есть на данный момент:

// This function is called from another thread when connection lost 
// is detected (i.e. when the client fails to receive a `pong` 
// message in time)
void WebSocketClient::force_disconnect_() {
  LOG_ERROR << "trying to force disconnect ws client ...";
  uWS::WebSocket<uWS::CLIENT>* socket_copy = nullptr;
  {
    std::lock_guard<std::mutex> lock(socket_mutex_);
    socket_copy = socket_;
    socket_ = nullptr;
  }
  if (socket_copy) {
    uWS::Group<uWS::CLIENT>::from(socket_copy)->terminate();
    LOG_ERROR << "ws client force disconnected";
  }
}

void WebSocketClient::websocket_thread_func_() {
  uWS::Hub h;
  h.onConnection([this](uWS::WebSocket<uWS::CLIENT> *ws, uWS::HttpRequest req) {
    std::lock_guard<std::mutex> lock(socket_mutex_);
    socket_ = ws;
  });

  h.onDisconnection([&h, this](uWS::WebSocket<uWS::CLIENT> *ws, 
    int code, char* message, size_t length) {
    LOG_INFO << "websocket to " << addr_ << " disconnected with code " << code 
        << ", msg " << std::string(message, length);
    std::lock_guard<std::mutex> lock(socket_mutex_);
    socket_ = nullptr;
    // The callback is called and this line of log is generated
    LOG_INFO << "onDisconnection finish";
  });

  h.onError([&h, this](void* user_data) {
    LOG_ERROR << "error from server";
  });

  h.onPong([this](uWS::WebSocket<uWS::CLIENT> *ws, char* msg, size_t length){
    alive_ = true;
  });

  LOG_INFO << "connecting to " << addr_;
  h.connect(addr_, nullptr);
  // this function never returns
  h.run();
  LOG_INFO << "connection to " << addr_ << " end, websocket thread can be joined.";
}
...