现在网上有很多种针对网络状态检测的方法,在此做一个简单的分析和总结。
总体来说一共有七种。
一、 InternetAttemptConnect函数
这个函数可以说非常简单,只是尝试计算机连接到网络。并不考虑是用什么方式连接。当成功连接到网络的时候,函数返回ERROR_SUCCESS,也就是0。函数的参数永远都是0。
有一点需要注意的是,当计算机是用“小猫”也就是拨号的方式上网的时候,在执行InternetAttemptConnect这个函数时,会自动激活拨号连接功能。这也就是很多软件使用的拨号连接功能。比如Foxmail和FlashGet。它跟IE的连网状态有时候不统一。
Example:
TCHAR tszDebugMsg[100] = {0};
DWORD dwres = InternetAttemptConnect(0);
if (dwres != ERROR_SUCCESS )
{
_stprintf_s(tszDebugMsg, 100, TEXT("InternetAttemptConnect failed error code is %d.\r\n"), dwres);
}
else
{
_stprintf_s(tszDebugMsg, 100, TEXT("We can connect to internet, not consider connect mode~~\r\n"));
}
OutputDebugString(tszDebugMsg);
二、 检查远程主机状态函数:InternetCheckConnection
这个函数的作用和PING命令是一样的,可以检查远程主机是否连接。如果连接成功返回TRUE,如果连接失败返回FALSE。通过上述的方法只能检测出当前计算机是否物理联网,即网线是否接好,网卡是否能顺利工作,不能确定是否能够实现获得 Internet 服务,即是否能和 ISP 进行 Internet 连接。它跟IE的连网状态有时候不统一。
缺点:如果断网,或者对应的服务器没开的话,会导致等待,卡死的现象。并且在in proxy environment 下如果设置了proxy server in IE (Internet Option->Connections->Lan Setting->Proxy Server") 获得的返回值一直是false。(这个题一直没找到原因,如有知道原因的还请不吝赐教O(∩_∩)O~)
Example:
BOOL bres = InternetCheckConnection(NULL, FLAG_ICC_FORCE_CONNECTION, 0);
if (!bres)
{
_stprintf_s(tszDebugMsg, 100, TEXT("InternetCheckConnection failed error code is %d.\r\n"), GetLastError());
}
else
{
_stprintf_s(tszDebugMsg, 100, TEXT("We can get long-distance host connect, physical connect sucess~~\r\n"));
}
OutputDebugString(tszDebugMsg);
三、 InternetQueryOption函数
InternetQueryOption 函数的检测结果只能表明当前的 Internet 设置是可用的, 并不能表示计算机一定能访问 Internet,例如网线掉了,网卡突然坏了之类的错误就没法检测出来,要想检测当前计算机是否能够获得 Internet 服务了必须跟InternetCheckConnection()两个结合起来使用。它跟IE的连网状态有时候不统一。
Example:
BYTE btInetSet[100] = {0};
DWORD dwInetSetLen = 100;
BOOL bres = InternetQueryOption(NULL, INTERNET_OPTION_CONNECTED_STATE, btInetSet, &dwInetSetLen);
if (!bres)
{
_stprintf_s(tszDebugMsg, 100, TEXT("InternetQueryOption failed error code is %d.\r\n"), GetLastError());
}
else
{
_stprintf_s(tszDebugMsg, 100, TEXT("We can get Internet service, internet settting ok~~\r\n"));
}
OutputDebugString(tszDebugMsg);
四、 检查本地网络连接状态并取得网络连接方式函数:InternetGetConnectedState
缺点是:若当前连接不是用wininet方法建立的,则返回值可能不准确。它跟IE的连网状态有时候不统一。
Example:
bres = InternetGetConnectedState(&dwFlags, 0);
if (!bres)
{
_stprintf_s(tszDebugMsg, 100, TEXT("InternetGetConnectedState failed error code is %d.\r\n"), GetLastError());
}
else
{
_stprintf_s(tszDebugMsg, 100, TEXT("InternetGetConnectedState sucess status is 0x%x ~~\r\n"),dwFlags);
}
OutputDebugString(tszDebugMsg);
五、 RAS 方法(Remote Access Service)
先用RasEnumConnections函数返回整个RAS集合,再用RasGetConnectStatus函数判断第一个 RAS连接的状态。RAS方法的最大优点是:不管当前连接是否是用wininet建立的,RAS 方法均可对在线状态做出正确判断。只能针对adsl拨号上网的用户。(此法只是参照网上解法,具体并未实现过)
六、 注册表法
在线时,注册表的“\HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\RemoteAccess”处有键值“Remote Connection”,且其值不为零;不在线时,该处无“Remote Connection”键值(当本次系统启动后从未拨号成功时),或者其值为零(表明曾拨号成功,但现在已断掉)。 这个方法很老了,有些系统不支持了。(此法只是参照网上解法,具体并未实现过)
七、ping命令实现
个人觉得这个方法不是非常好用,在这里就不做赘述了。
====================================================================================
上面的这些方法都或多或少的有些问题,下面是我自己实现的来测试网络状态的函数,它跟IE的连网状态是统一。
(1) InternetStatus.h
#pragma once
#include <Windows.h>
// Test URL
#define INTENET_STATUS_TESTURL_MS TEXT("http://www.msn.com/")
#define INTENET_STATUS_TESTURL_ASUS_APRPSERVER TEXT("http://www.baidu.com/")
// User Agent
#define USER_AGENT TEXT("SP_InetStatus/1.0")
BOOL IsInternetConnected(void);
(2) InternetStatus.cpp
// Include
#include "InternetStatus.h"
#include <WinInet.h>
#include <tchar.h>
// Lib
#pragma comment(lib,"wininet.lib")
// Error Msg length
#define DEBUGRMSG_LEN 100
// Error Msg
TCHAR tszDebugMsg[DEBUGRMSG_LEN] = {0};
// MY_InternetOpenUrl Sub Method
BOOL MY_InternetOpenUrl(HINTERNET hInternet, LPCTSTR lpszUrl)
{
HINTERNET hConnectOpenUrl = NULL;
// Open target url
hConnectOpenUrl = InternetOpenUrl(hInternet, lpszUrl, NULL, 0, INTERNET_FLAG_RELOAD, 0);
if (hConnectOpenUrl == NULL)
{
_stprintf_s(tszDebugMsg, DEBUGRMSG_LEN, TEXT("\r\n InternetOpenUrl %s failed, error code is %d! \r\n"), lpszUrl, GetLastError());
OutputDebugString(tszDebugMsg);
return FALSE;
}
// Close Internet Handle
InternetCloseHandle(hConnectOpenUrl);
_stprintf_s(tszDebugMsg, DEBUGRMSG_LEN, TEXT("\r\n InternetOpenUrl %s sucess~~ \r\n"), lpszUrl);
OutputDebugString(tszDebugMsg);
return TRUE;
}
// IsInternetConnected Method
BOOL IsInternetConnected()
{
HINTERNET hInternetOpen = NULL;
BOOL brtnInf = TRUE;
hInternetOpen = InternetOpen(USER_AGENT, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
if (hInternetOpen == NULL)
{
_stprintf_s(tszDebugMsg, DEBUGRMSG_LEN, TEXT("\r\n InternetOpen failed error code is %d! \r\n"), GetLastError());
OutputDebugString(tszDebugMsg);
brtnInf = FALSE;
goto END_RETURN;
}
BOOL bres = MY_InternetOpenUrl(hInternetOpen, INTENET_STATUS_TESTURL_MS);
if (!bres)
{
bres = MY_InternetOpenUrl(hInternetOpen, INTENET_STATUS_TESTURL_ASUS_APRPSERVER);
if (!bres)
{
OutputDebugString(TEXT("\r\n InternetOpenUrl Failed after try two URL! \r\n"));
brtnInf = FALSE;
}
}
END_RETURN:
// Close HINTERNET
if (hInternetOpen)
{
InternetCloseHandle(hInternetOpen);
}
return brtnInf;
}
(3) how to using.
#include "InternetStatus.h"
int _tmain(int argc, _TCHAR* argv[])
{
if (IsInternetConnected())
{
OutputDebugString(TEXT("\r\n Internet Connected ~_~ \r\n"));
}
}
有什么问题大家可以共同讨论O(∩_∩)O~