[C++]網卡斷線偵測

最近遇到一個網卡偵測link狀態的難題,其實就是希望得知在網卡link down的時候,使用者能立即知道。就像windows控制台裡頭的網路介面卡設定的圖示,把線拔掉之後,就會立即變成灰色的icon那樣。

因為原本產品是用usb網卡端口,所以透過winpcap的方式,只要簡單知道網卡不見了(usb被拔掉之後,就會在清單中消失),就可以判定是斷線了。但是RJ-45端口不是這樣子。需要一些方法。我列舉三種方法,其中沒有ping的方法,ping是去偵測遠端設備的狀況,不是針對local PC端某張網卡。

【方法一】利用winpcap的PacketOpenAdapter方法。他需要使用到底層一點的Packet.lib。

#include ".\winpcap\v4_1_2\Packet32.h"

LPADAPTER adapter_ = PacketOpenAdapter(alldevs->name);
PACKET_OID_DATA *linkStateOid_ = new PACKET_OID_DATA;
memset(linkStateOid_, 0, sizeof(PACKET_OID_DATA) + sizeof(unsigned int));
linkStateOid_->Oid = OID_GEN_MEDIA_CONNECT_STATUS;
linkStateOid_->Length = sizeof(unsigned int);
if (PacketRequest(adapter_, 0, linkStateOid_))
{
   unsigned int state;
   if (linkStateOid_->Length == sizeof(state))
   {
     memcpy((void*)&state, (void*)linkStateOid_->Data, linkStateOid_->Length);
     if (state == 0) //link up
     else if (state == 1) //link down
   }
}

【方法二】利用Windows WMI 的 Win32_NetworkAdapter class。透過WQL查詢,將結果放至列舉清單,最後再從清單中,取出NetConnectionStatus參數比對結果。

這邊有Microsoft提供的好用C++範例

IWbemServices *pSvc = NULL;
hres = pSvc->ExecQuery( L"WQL", L"SELECT * FROM Win32_NetworkAdapter", WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator);
IWbemClassObject *pclsObj = NULL;
while (pEnumerator)
{
   HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
   hr = pclsObj->Get(L"NetConnectionStatus", 0, &vtProp, 0, 0);// Uint16
   //vtProp.uiVal即為結果
   if(vtProp.uiVal == 7) // link down
   else if(vtProp.uiVal == 2)//link up
   //....
}

【方法三】利用GetAdaptersAddresses列舉出PIP_ADAPTER_ADDRESSES,比對OperStatus參數。

PIP_ADAPTER_ADDRESSES pAddresses = new IP_ADAPTER_ADDRESSES;
PIP_ADAPTER_ADDRESSES ptmpAddr;
GetAdaptersAddresses(family, flags, NULL, pAddresses, &BufSize);
ptmpAddr = pAddresses;
while(NULL!=ptmpAddr){
   if(ptmpAddr->OperStatus == IfOperStatusUp) //link up
   else //link down
   ptmpAddr = ptmpAddr->Next;
}

--結構--
整個程式顯得很亂,大概就是分成三種方法個別開個thread,利用#define來區分。每個thread都是持續不斷的去查找選擇到的網卡的link狀態(中間還是有delay 100毫秒)。直到程式關閉。所以看起來就像是一有變化,在0.1秒左右就會知道狀態了。
分別用#define設定的選取方法去查找。不過畫面上好像看不出來三者差異就是了。


--結論--
方法一:最簡單,使用到winpcap查找送收包的,可以直接套用參數。
方法二:很複雜,最多種資訊,可以獲得更詳細的資料。只是每次都要做那麼一大段。
方法三:難易度介於一二之間,只是若還要透過pcap來送收包,那還要透過AdapterName比對出index才不會亂掉。若是單純檢視用,算是最方便的。

--程式執行圖--

--完整Source Code(VC++ 2008 vaildated)--
AdapterStatus.7z

0 意見:

搜尋此網誌

總網頁瀏覽量

TK呱呱

Made with by TK