Qt QTcpSocket 對連接服務器中斷的不同情況進行判定


簡述

對於一個C/S結構的程序,客戶端有些時候需要實時得知與服務器的連接狀態。而對於客戶端與服務器斷開連接的因素很多,現在就目前遇到的情況進行一下總結。

分為下面六種不同情況

  1. 客戶端網線斷開
  2. 客戶端網絡斷開
  3. 客戶端通過HTTP代理連接服務器,代理機器斷開代理
  4. 客戶端通過HTTP代理連接服務器,代理機器的網絡斷開
  5. 客戶端通過HTTP代理連接服務器,代理機器的網線斷開
  6. 服務器斷開

同時對於以上六種情況又分為連接服務器之前和連接上服務器之后,下面就分別對不同的情況進行分析。

開始連接服務器之前

1、 客戶端網線斷開 
此時用socket調用connectToHost方法連接服務器會立即觸發QTcpSocket的error信號,我們可以綁定相應的槽去處理連接失敗的結果。


2、 客戶端網絡斷開 
3、 客戶端通過HTTP代理連接服務器,代理機器斷開代理 
4、 客戶端通過HTTP代理連接服務器,代理機器的網絡斷開 
5.、客戶端通過HTTP代理連接服務器,代理機器的網線斷開 
6、 服務器斷開 
此時用socket調用connectToHost方法連接服務器並不會立即觸發QTcpSocket的error信號,而是經過40s+的連接等待超時發出error信號,見下圖。

這里寫圖片描述


已經連接上服務器

1、 客戶端網線斷開 
此時socket不會發送error信號,也不會發送disconnect信號,查詢資料是因為網線斷開是屬於物理鏈路層,tcp無法察覺到,socket仍處於連接狀態。


2、 客戶端網絡斷開 
3、 客戶端通過HTTP代理連接服務器,代理機器斷開代理 
4、 客戶端通過HTTP代理連接服務器,代理機器的網絡斷開 
5.、客戶端通過HTTP代理連接服務器,代理機器的網線斷開

第二和第三種情況下會立即觸發error信號,而第四和第五種情況下會等待30s左右會發送error信號。


6、 服務器斷開 
此時socket會發送disconnect信號,可以綁定相應的槽去處理服務器斷開的情況。

檢測與服務器斷開的另外方法

對於有些程序(客戶端)需要立即知道與服務端連接狀態,而不是等待幾十秒之后才有信號通知到或者根本就檢測不出與服務器斷開,除了利用QTcpSocket提供的信號(有幾種情況不會發出信號或發出信號延遲),這里列出另外幾種處理方法。

1、發送心跳包,即客戶端每隔一段時間發送一條報文,報文不需附帶具體內容,只需要讓服務端知道這是一條心跳報文,並回發一條消息,客戶端收到這條消息后就得知與服務器保持連接的狀態。

檢測本地網絡,定義一個時鍾,每次timeout去檢測本地的網絡,關於怎么判斷本地網絡是否通暢呢?

2、可以用windows提供的IsNetworkAlive方法,返回為false為網絡異常。加上頭文件為#include “Sensapi.h”。同時需要包含Sensapi.lib。 
(通過IsNetworkAlive方法判斷本地網絡,在客戶端已經連接上服務器,並且禁用網絡時會立即發送error信號,在error信號綁定的槽中去調用這個方法發現返回值為true,因為這種情況下禁用網絡后會立即發送error信號,調用IsNetworkAlive方法時可能立即檢測不到網絡異常。如果通過斷點的方式,在調用IsNetworkAlive時就會返回false)

    DWORD dwFlag;
    if (FALSE == IsNetworkAlive(&dwFlag)) { qDebug() << "NetWorkError"; }

注意:

但是這種方法,在本地存在虛擬機並且虛擬機開啟時會失效,因為IsNetworkAlive會檢測本地所有的網絡,在網線斷開后,可能檢測到虛擬機網絡正常,導致返回ture。

3、如果有自己的服務器就ping服務器(前提服務器不會掛),否則就ping一個相對可靠的IP (比如百度),通過看他ping的結果怎么樣. 
同時在C++ 實現 ping 功能&& 域名(URL)解析實際 IP地址 這篇博客中用C++實現了 ping的 功能,有興趣的小伙伴可以看一看,了解一下。

QProcess *cmd = new QProcess; cmd->start("ping www.baidu.com"); // 等待ping 的結果 while (cmd->waitForFinished()) { QString result = QString::fromLocal8Bit(cmd->readAll()); qDebug() << result; }

QHostInfo::lookupHost("www.baidu.com", this, SLOT(lookedUp(QHostInfo))); void lookedUp(QHostInfo &host) { qDebug() << host.addresses().first().toString(); } //得到IP 地址 就是在互聯網上 如果不能得到 就不行

4、QNetworkConfigurationManager::isOnline()。 
當然這個只能檢查你是否有網絡鏈接,而不能檢測你是否連接到互聯網。


對於需要自動重連的客戶端可以通過以上方法,在判斷出與服務器斷開后可以重新連接,或者通過超時定時器進行重連,方法很多,在於嘗試。

 

轉自:http://blog.csdn.net/GoForwardToStep/article/details/52300335?locationNum=4


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM