一般我们判断是否能够访问指定的IP地址时,一般都是采用PING或者尝试连接到指定的TCP端口的方式,在上面的基础上,实际上通过尽快的排除明显不可能访问的目标,来加快测试的速度。
下面的C++代码提供给大家,方便的判断是否能够路由到指定的目标:
/*判断是否能够路由到指定的IP
Parameters
ARemote : 用来确定网卡的远程地址
Returns
在以下情况下,返回false:
1.无法路由到远程地址;
2.网卡被禁用或网卡断开连接
否则,返回true
*/
bool __fastcall CanRouteTo(const in_addr &ARemote)
{
MIB_IFTABLE *ATable;
DWORD ASize=0;
int ARetVal=0;//Unknown
if(GetIfTable(NULL,&ASize,false)==ERROR_INSUFFICIENT_BUFFER)
{
ATable=(MIB_IFTABLE *)malloc(ASize);
PMIB_IPFORWARDTABLE pIpForwardTable=NULL;
try
{
if(GetIfTable(ATable,&ASize,false)==ERROR_SUCCESS)
{
ASize=0;
int ALastMatric;
if(GetIpForwardTable(pIpForwardTable, &ASize, false)==ERROR_INSUFFICIENT_BUFFER)
{
pIpForwardTable = (PMIB_IPFORWARDTABLE)malloc(ASize);
if(GetIpForwardTable(pIpForwardTable, &ASize, false)==ERROR_SUCCESS)
{
for(int j=0; (j<pIpForwardTable->dwNumEntries)&&(ARetVal==0); j++)
{
if((pIpForwardTable->table[j].dwForwardMask&ARemote.S_un.S_addr)==pIpForwardTable->table[j].dwForwardDest)
{
if(pIpForwardTable->table[j].dwForwardType>=3)
{
for(DWORD i=0; i<ATable->dwNumEntries; i++)
{
if(pIpForwardTable->table[j].dwForwardIfIndex==ATable->table[i].dwIndex)
{
switch(ATable->table[i].dwOperStatus)
{
case MIB_IF_OPER_STATUS_OPERATIONAL:
case MIB_IF_OPER_STATUS_CONNECTED:
ARetVal=1;//Connected
break;
default:
ARetVal=2;//Disconnected
break;
}
break;
}
}
}
}
}
}
}
}
}
__finally
{
free(ATable);
if(pIpForwardTable)
free(pIpForwardTable);
}
}
return (ARetVal==1);
}这个函数的缺陷是每次是每次都会枚举路由表和网卡状态,实际上进一步优化的话,我们可以通过缓存路由表来提高效率。这时你可能有新的疑问?路由表变了怎么办?IP地址变了怎么办?网卡断开或者被禁用了我怎么检测到呢?
好吧,我们承认这些都是合理担忧,所以我这里告诉大家两个API,NotifyRouteChange和NotifyAddrChange可以分别用于检测路由表和地址的变更。您可能认为没有网卡检测功能,实际上,网卡被禁用或才启用时,路由表会发生变更,所以可以满足上面的要求了。只需要在检测到路由表和IP变更时,更新下路由表就OK了。
同样的,大家看实现的代码,可以看到代码中已经实际包含了网卡是否断开的检测,可以提取出来,判断网卡是否下线。就不在这里重复了。
