簡體   English   中英

斷開連接后重新連接Boost Beast(ASIO)WebSocket和HTTP連接時出錯

[英]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

所以我有兩個問題:

  1. 如果Internet斷開並且無法正確關閉tcp,我們如何關閉連接。
  2. 在重新連接boost::beast中的變量之前(或者就此而言, boost::asio作為boost::beast建立在asio之上)需要重置

嘗試調試此程序已花費了幾個小時。 任何幫助表示贊賞

編輯

所以我找出了哪里出了問題。 艾倫·比特爾斯(Alan Birtles)和文妮·法爾科(Vinnie Falco)都是對的。 在您的ping計時器到期(並且尚未返回任何處理程序)之后,關閉無效的ssl連接的方法是

  1. 在您的計時器處理程序中
 _stream->lowest_layer().close(); 

對於websocket

 _ws->lowest_layer().close(); 
  1. 等待您的一個處理程序(通常為讀取處理程序)返回錯誤(通常為boost :: asio :: error :: operation_aborted錯誤)。 從那里,將下一個重新連接的開始排隊。 (不要在步驟1之后立即將重新連接排入隊列,這將導致我遇到的內存問題。我知道這是asio 101,但很容易忘記)

  2. 對於重置套接字,所需要做的只是重置流

 _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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM