[英]Error reconnecting boost beast (asio) websocket and http connection after disconnect
我正在創建使用ssl Websocket連接和ssl Http(Keep-Alive)連接連接到服務器的客戶端應用程序,並且正在使用boost::beast
包來執行相同的操作。 為了檢測到斷開連接,我已經實現了一種簡單的乒乓機制。 這些都可以正常工作,但是在處理乒乓球失敗時出現問題。 問題如下:
為了測試我的代碼,我連接到遠程服務器,發送了幾則消息,然后關閉了我的wifi。 作為一定時期后預計它檢測到它並沒有從服務器收到任何消息,它試圖做一個async_shutdown
為HTTP連接和async_close
為WebSocket連接。 我注意到的第一件事是,這兩個呼叫都阻塞了各自的線程,直到wifi備份為止。
wifi啟動后,應用程序嘗試在重新連接之前重置流:
void HttpKeepAliveConnection::recreateSocket() { _receivedPongForLastPing = true; _sslContext.reset(new boost::asio::ssl::context({boost::asio::ssl::context::sslv23_client})); _stream.reset(new HttpStream(_ioContext, *_sslContext)); }
並為websocket重置ws變量:
void WebsocketConnection::recreateSocket() { _receivedPongForLastPing = true; _sslContext.reset(new boost::asio::ssl::context({boost::asio::ssl::context::sslv23_client})); _ws.reset(new WebSocket(_ioContext, *_sslContext)); }
不幸的是,它在on_connect或on_ssl_handshake均失敗。 以下是我的日志:
156 AsioConnectionBase.cpp:53(2018-08-06 15:34:38.458536)[0x00007ffff601e700]:開始的連接序列。 連接名稱:HttpKeepAliveConn
157 AsioConnectionBase.cpp:122(2018-08-06 15:34:38.459802)[0x00007ffff481b700]:建立與目標的連接失敗。 連接失敗。 連接名稱:HttpKeepAliveConn。 主持人:xxxxxxxxx。 端口:443。錯誤:操作已取消
158 APIManager.cpp:175(2018-08-06 15:34:38.459886)[0x00007ffff481b700]:收到來自連接的錯誤回調。 幾秒鍾內重新啟動連接。 連接名稱:HttpKeepAliveConn
159 AsioConnectionBase.cpp:53(2018-08-06 15:34:39.460009)[0x00007ffff481b700]:開始的連接序列。 連接名稱:HttpKeepAliveConn
160 HttpKeepAliveConnection.cpp:32(2018-08-06 15:34:39.460515)[0x00007ffff481b700]:SSL握手失敗。 連接失敗。連接名稱:HttpKeepAliveConn。 主持人:xxxxxxxxx。 端口:443。錯誤:錯誤的文件描述符
161 APIManager.cpp:175(2018-08-06 15:34:39.460674)[0x00007ffff481b700]:收到來自連接的錯誤回調。 幾秒鍾內重新啟動連接。 連接名稱:HttpKeepAliveConn
所以我有兩個問題:
boost::beast
中的變量之前(或者就此而言, boost::asio
作為boost::beast
建立在asio之上)需要重置 嘗試調試此程序已花費了幾個小時。 任何幫助表示贊賞
編輯
所以我找出了哪里出了問題。 艾倫·比特爾斯(Alan Birtles)和文妮·法爾科(Vinnie Falco)都是對的。 在您的ping計時器到期(並且尚未返回任何處理程序)之后,關閉無效的ssl連接的方法是
_stream->lowest_layer().close();
對於websocket
_ws->lowest_layer().close();
等待您的一個處理程序(通常為讀取處理程序)返回錯誤(通常為boost :: asio :: error :: operation_aborted錯誤)。 從那里,將下一個重新連接的開始排隊。 (不要在步驟1之后立即將重新連接排入隊列,這將導致我遇到的內存問題。我知道這是asio 101,但很容易忘記)
對於重置套接字,所需要做的只是重置流
_stream.reset(new HttpStream(_ioContext, _sslContext));
對於websocket
_ws.reset(new WebSocket(_ioContext, _sslContext));
我不認為asio::ssl::stream
在關閉后不能再次使用。
如果Internet斷開並且無法正確關閉tcp,我們如何關閉連接。
只需允許銷毀套接字或流對象。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.