我正在使用uWebsockets的v0.14构建与WebSocket服务器进行交互的WebSocket客户端。我发现Websocket客户端的一个令人烦恼的行为是,当Internet连接断开(出于测试目的,我直接从互联网断开计算机的连接)时,Websocket客户端没有意识到这一点,并且onDisconnection
和onError
都没有叫做。经过一番谷歌搜索后,我了解到this is an expected behavior,并且我必须手动设置一种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.";
}