簡述
在網絡操作中,經常會由于各種原因引起網絡連接配接逾時,究竟何為網絡連接配接逾時?
網絡連接配接逾時:在程式預設的等待時間内沒有得到伺服器的響應
逾時原因
引起網絡連接配接逾時的原因很多,下面,列舉一些常見的原因:
- 網絡斷開,不過經常顯示無法連接配接
- 網絡阻塞,導緻你不能在程式預設等待時間内得到回複資料包
- 網絡不穩定,網絡無法完整傳送伺服器資訊
- 系統問題,系統資源過低,無法為程式提供足夠的資源處理伺服器資訊
- 裝置不穩定,如網線松動、接口沒插好等等
- 網絡注冊時系統繁忙,無法回應
- 網速過慢,如 使用 BT 多線程下載下傳,線上收看視訊等大量占用帶寬的軟體 ,若使用共享帶寬還要防範他人惡意占用帶寬
- 計算機感染了惡意軟體,計算機病毒,計算機木馬等
Qt 中的網絡連接配接逾時
在 Qt 中,關于 QNetworkAccessManager、QNetworkRequest 和 QNetworkReply 的文檔中,找到了有關逾時相關的錯誤 QNetworkReply::NetworkError。
常量 QNetworkReply::TimeoutError:
the connection to the remote server timed out
瞬間欣喜若狂,既然有逾時錯誤,必然有設定逾時的接口吧!遺憾,遺憾,遺憾。。。重要的事情說 3 遍,翻遍了官方文檔,能和逾時扯上關系的就這麼一個簡單的常量說明(當然還有 QNetworkReply::ProxyTimeoutError)。
這種情況下,我們隻能自己去處理逾時了。
如何處理逾時
解決思路:
- 使用 QTimer 啟動一個單次定時器,并設定逾時時間。
- 在事件循環退出之後,判斷定時器的狀态,如果是激活狀态,證明請求已經完成;否則,說明逾時。
來看一個簡單的例子 - 擷取 Qt 官網 網頁内容:
QTimer timer;
timer.setInterval(30000); // 設定逾時時間 30 秒
timer.setSingleShot(true); // 單次觸發
首先,定義一個 QTimer,設定逾時時間為 30000 毫秒(30 秒)并設定為單次觸發。然後,使用 QNetworkRequest 實作一個簡單的網絡請求,通過 QNetworkAccessManager::get() 開始擷取 Qt 官網的 HTML 頁面内容。因為請求過程是異步的,是以通過使用 QEventLoop 啟動一個事件循環讓其同步處理,并将 QTimer 的 timeout() 信号以及 QNetworkReply 的 finished() 信号連接配接至其 quit() 槽函數,保證在定時器過期之後或者網絡響應完成後事件循環得到退出,不至于一直處于阻塞狀态。
如上所述,事件循環退出的兩種情況:
- QTimer 30 秒到期,逾時
- 網絡連接配接響應完成
是以,當 QTimer::isActive() 激活的情況下,證明響應完成,還尚未逾時。這時需要先調用 QTimer::stop() 來停止定時器,再對響做進一步處理。否則,進行逾時處理 - QNetworkReply::abort() 立即中止操作并關閉網絡連接配接。
封裝類
既然以後會經常用到,那麼還是提供一個封裝類 QReplyTimeout 專門處理逾時。
*>(parent());
if (reply->isRunning()) {
reply->abort();
reply->deleteLater();
emit timeout();
}
}
};
由于 QNetworkReply 和 QReplyTimeout 是父子關系,是以 QReplyTimeout 将被自動銷毀。