今天有项目需求,需要实时检测网络连接状态,起码要做的和QQ微信差不多,根据网络上以及MSDN提供的一些API,比如InternetGetConnectedState和IsNetworkAlive均没有达到预期效果,或者是有各种各样的问题,比如说API InternetGetConnectedState,这个API就有延时的问题,亲测我的机器延时为5秒,而IsNetworkAlive仅仅只能检测到网线连接,但是不能检测到网络连通,只能抛弃这两个函数。通过不断google和翻看MSDN,终于找到一个实现,即实现Network List manager(NLM)的相关方法和回调即可。
首先,从INetworkListManagerEvents派生一个类,并实现相关COM接口函数
#pragma once
#include <atlcom.h>
#include <netlistmgr.h>
#include <netlistmgr.h>
class NetworkEventHandler : public INetworkListManagerEvents
{
public:
NetworkEventHandler(void);
virtual ~NetworkEventHandler(void);
STDMETHODIMP QueryInterface (REFIID riid, void** pIFace);
STDMETHODIMP_(ULONG) AddRef();
STDMETHODIMP_(ULONG) Release();
STDMETHODIMP ConnectivityChanged(NLM_CONNECTIVITY NewConnectivity);
private:
long m_lRefCnt;
};
cpp:
NetworkEventHandler::NetworkEventHandler(void) : m_lRefCnt(0)
{
}
NetworkEventHandler::~NetworkEventHandler(void)
{
}
STDMETHODIMP NetworkEventHandler::QueryInterface(REFIID refIID, void** pIFace)
{
*pIFace = NULL;
if(refIID == IID_IUnknown || refIID == __uuidof(INetworkListManagerEvents))
{
*pIFace = (IUnknown*)(INetworkListManagerEvents*)(this);
}
if (*pIFace == NULL)
{
return E_NOINTERFACE;
}
((IUnknown*)*pIFace)->AddRef();
return S_OK;
}
STDMETHODIMP_(ULONG) NetworkEventHandler::AddRef()
{
m_lRefCnt++;
return m_lRefCnt;
}
STDMETHODIMP_(ULONG) NetworkEventHandler::Release()
{
m_lRefCnt--;
if(m_lRefCnt == 0)
{
delete this;
return (0);
}
return m_lRefCnt;
}
STDMETHODIMP NetworkEventHandler :: ConnectivityChanged( NLM_CONNECTIVITY NewConnectivity)
{
bool bInternet = false;
if((NewConnectivity & NLM_CONNECTIVITY_IPV4_INTERNET) || (NewConnectivity & NLM_CONNECTIVITY_IPV6_INTERNET))
{
bInternet = true;
//网络已经连通,做点啥事
}
else
{
//网络已经不通,做点啥事
}
return S_OK;
}
然后注册相关事件即可,
定义
CComPtr<INetworkListManager> m_pNLM;
NetworkEventHandler * m_pSink;
DWORD m_dwCookie;
注册:
m_pNLM.CoCreateInstance(CLSID_NetworkListManager);
m_pSink = new NetworkEventHandler();
if (SUCCEEDED (m_pSink->QueryInterface(IID_IUnknown, (void**) &m_pSink)))
{
AfxConnectionAdvise (m_pNLM, __uuidof(INetworkListManagerEvents), m_pSink, FALSE, &m_dwCookie); // Advising for Events
}
最后程序结束,释放:
AfxConnectionUnadvise (m_pNLM, IID_INetworkListManagerEvents, m_pSink, FALSE, m_dwCookie);
m_pSink->Release();
当网络连接状态改变时,ConnectivityChanged就会收到通知了