使用VB+API,请问如何读取、添加、删除、更改本机的路由表?
希望能有代码的例子。先谢了。
希望能有代码的例子。先谢了。
解决方案 »
- 怎么判断一个控件是否在窗体上,如判断textbox是否在form上。
- 在线等待,小弟有个多系统引导方面的问题比较困惑想请家帮助谢谢!
- 今天在火车上学会了一首诗
- 怎样模拟发送系统级的的按键信息??????????(高分求答案!)
- 请问!!
- 怎么编程用vb打开visio文件,并且不需要visio环境的存在
- 问题(在线等待)
- 如何用vba实现打开其他幻灯片并触发幻灯片上的按钮事件?
- 请大家帮忙看看这段代码,关于WritePrivateProfileString,GetPrivateProfileString
- 怎么样在vb中打开一个excel文件呢,是用这个CreateFile api函数吗?
- 在VB6里如何捕捉RUNTIME错误?
- 请进!!!!!!!!!!!!!!!!!!!
例子是C++的,不好意思。其中最主要的两个函数是GetNumberOfInterfaces和GetInterfaceInfo,前者指出网络接口的个数,后者提取网络接口的信息。对于第一个函数要说明的一点是它好象并没有返回正确的值,因为据MSDN描述:一个网络接口是网卡的逻辑抽象,它们是一对一的关系。而实际情况是我的机器上只有一张网卡,这个函数却返回了2。实际上,因为每个系统都附加有一个调试用的网络接口,这个接口的IP地址是127.0.0.1子网掩码是255.0.0.0。这个结果可以从程序的输出看出来。由GetInterfaceInfo返回的IP_INTERFACE_INFO结构中也有一个NumAdapters整型的数据域记录了正确的网卡。然后对于GetInterfaceInfo要注意的是它也必须被调用两次,第一次获取缓冲大小,第二次才是取值。然后再次让我感到其怪的是GetInterfaceInfo返回的IP_INTERFACE_INFO不象上面的结构是用链表,而是用的动态数组的方法(到现在什么线性结构都用上了),所以遍历其中每一个元素的代码变成:
for(int i=0;iNumAdapters;i++)
{
cout<<"Adapter index:"<Adapter[i].Index<Adapter[i].Name<
IP_INTERFACE_INFO结构的解释如下:
typedef struct _IP_INTERFACE_INFO {
LONG NumAdapters;
// 动态数组中网络接口元素的个数,通过它来遍历数
//组
IP_ADAPTER_INDEX_MAP Adapter[1];
// 网络接口数据数组
} IP_INTERFACE_INFO,*PIP_INTERFACE_INFO;其中的IP_ADAPTER_INDEX_MAP结构如下:
typedef struct _IP_ADAPTER_INDEX_MAP {
ULONG Index;
// 网卡索引
WCHAR Name[MAX_ADAPTER_NAME];
// 网卡名
} IP_ADAPTER_INDEX_MAP, * PIP_ADAPTER_INDEX_MAP;提取IP信息
这部分显然和提取网络接口信息部分是相同的。设置本地网络
设置的过程与提取过程其实是换汤不换药。我不想在这里演示每一个函数的用法,所以只使用了一个(我认为)最常用的函数AddIPAddress。这个函数能够设置本地网络的IP。但不幸的是,这个IP是临时的,当系统重新启动或者发生其它的PNP事件的时候这个IP就不存在了。那么有人会问这有什么用呢?实际上,每个网络接口卡都可以绑定多个IP,所以在网络环境恶劣的情况下(如校园网)同时预备多个IP以防断线是有必要的。必须指出的是这种临时的IP在网络通讯时可能导致的问题现在还没有测试过,诸如CODEGURU,CSDN,MSDN,或者TECHREPUBLIC对这套API也没有详细的解释(虽然它很有用)。其它的API函数
这些函数能够让你察看或者设置网络数据报文方面的信息。比方GetIpStatistics、GetIcmpStatistics函数能够让你查看当前IP数据报和ICMP数据报的流量,以及废弃的数据报数量等等。使用这些函数你可以构建自己的网络监控程序检察网络中的故障。你也可以使用SetIpStatistics 函数来设置相应的IP协议栈属性,缩短或者延长IP数据报的缺省TTL值。然后你也可以使用GetIpForwardTable、CreateIpForwardEntry 、DeleteIpForwardEntry、SetIpForwardEntry来分别获取IP路由表的信息,创建路由表项,删除路由表项和修改路由表项。也可以用GetBestRoute、 GetBestInterface获得到达指定IP的最好的路由点和网络接口。事实上,通过这些函数我们可以得到许多MIB变量(《使用TCP/IP协议实现网际互联》第二卷),通过这些MIB变量,我们可以非常快速的制作一个网络管理软件。 未涉及的部分
我们没有涉及IP Helper API中SendARP函数的使用。实际上,这个函数是我使用这套API的主要原因,它能够简单的发送ARP数据包并返回目标机器的MAC地址。我使用这个函数制作了另一个简单的IP查看程序,它能够查看局域网上哪些IP正在使用,并能够显示它们的MAC地址。如果把这些信息记录在文件中,我就可以统计出一天中哪些家伙的上网时间最长以及其上网的习性并能够知道哪些人更换了他们的网卡,也可以分析出这个网络的使用情况(我在学校的高峰时段统计出一个网段的254个IP中竟有236个正在使用,可见增加网段的必要了)。我将在后面的文章中说明这个程序的制作。我们也没有涉及这套API提供的当网络设置改变时向应用程序发出消息的异步通知功能。因为它们非常简单,与WINSOCK中WSAAsyncSelect的使用方法是一样的,就不再说明了。后话
讨论如何使用API函数也许会被一批"纯粹"的程序员所鄙视。但每次看到有人在论坛上急切的询问如何取得本机网关,IP地址,路由之类的信息的时候,我就觉得非常有必要介绍这一套API函数,它能够(至少在我看来)满足我们的大部分要求
附:演示程序源代码
// IpHelper.cpp : Defines the entry point for the console application.// #include "stdafx.h"#include "windows.h"#include "iostream.h"#include "iphlpapi.h" typedef DWORD(CALLBACK * PGNOINTERFACE)(PDWORD);//GetNumberOfInterfacestypedef DWORD(CALLBACK * PGAINFO)(PIP_ADAPTER_INFO,PULONG);//GetAdaptersInfotypedef DWORD(CALLBACK * PGIINFO)(PIP_INTERFACE_INFO,PULONG );//GetInterfaceInfotypedef DWORD(CALLBACK * PGIAT)(PMIB_IPADDRTABLE,PULONG,BOOL);//GetIpAddrTabletypedef DWORD(CALLBACK * PAIA)(IPAddr,IPMask,DWORD,PULONG,PULONG);//AddIPAddress int main(int argc, char* argv[]){ DWORD index=0; //函数指针 PGAINFO pGAInfo; //加载IP Helper API 所需的库文件 HINSTANCE hInst;//实例句柄 hInst=LoadLibrary("iphlpapi.dll"); if(!hInst) cout<<"iphlpapi.dll not supported in this platform!\n"; cout<<"net adapters information:"<<endl<<endl; //------------------------------------》获得网卡数据 pGAInfo=(PGAINFO)GetProcAddress(hInst,"GetAdaptersInfo"); PIP_ADAPTER_INFO pInfo=NULL,pInfoTemp=NULL; ULONG ulSize=0; pGAInfo(pInfo,&ulSize);//第一次调用,获取缓冲区大小 pInfoTemp=pInfo=(PIP_ADAPTER_INFO)new(char[ulSize]); pGAInfo(pInfo,&ulSize); //遍历每一张网卡 while(pInfo) { //网卡名 cout<<"adapter name: "<<pInfo->AdapterName<<endl; //网卡描述信息 cout<<"description: "<<pInfo->Description<<endl; //记录下它的索引值以便后面使用。 index=pInfo->Index; //物理地址的长度 cout<<"hardware address length: "<<pInfo->AddressLength<<endl; //显示物理地址 cout<<"hardware address:"; cout.setf(ios::hex); cout.unsetf(ios::dec); for(int i=0;i<(int)pInfo->AddressLength;i++) cout<<(unsigned int)pInfo->Address[i]; cout<<endl; cout.unsetf(ios::hex); cout.setf(ios::dec); //显示绑定于这张网卡之上的IP地址 cout<<"ip address bound to this chapter: "<<endl; PIP_ADDR_STRING pAddTemp=&(pInfo->IpAddressList); while(pAddTemp)/*遍历IP列表中的每一个元素*/ { cout<<pAddTemp->IpAddress.String<<endl; pAddTemp=pAddTemp->Next; } //显示当前使用的IP地址 //因为在离线状态下pInfo->CurrentIpAddress被置空,所以有必要做检查 if(pInfo->CurrentIpAddress) { cout<<"current ip using:"<<endl; pAddTemp=pInfo->CurrentIpAddress; while(pAddTemp)/*遍历IP列表中的每一个元素*/ { cout<<pAddTemp->IpAddress.String<<endl; pAddTemp=pAddTemp->Next; } } else cout<<"network malfunctioning,no ip is in use!\n"<<endl; //显示DHCP 服务器数据 cout<<"DHCP in use:"<<endl; pAddTemp=&(pInfo->DhcpServer); while(pAddTemp)/*遍历IP列表中的每一个元素*/ { cout<<pAddTemp->IpAddress.String<<endl; pAddTemp=pAddTemp->Next; } //将当前指针移向下一个 pInfo=pInfo->Next; } delete pInfoTemp;//回收无用内存 //------------------------------------》获得网卡数据部分结束 cout<<endl<<endl; //函数指针 PGNOINTERFACE pGNOInterface; PGIINFO pGIInfo; cout<<"network interfaces information:"<<endl<<endl; //------------------------------------》网络接口信息部分 //显示网络接口的个数 DWORD ulNumOfInterfaces=0; pGNOInterface=(PGNOINTERFACE)GetProcAddress(hInst,"GetNumberOfInterfaces"); pGNOInterface(&ulNumOfInterfaces); cout<<"U have "<<ulNumOfInterfaces<<" network interfaces\n"; //获取网络接口信息 pGIInfo=(PGIINFO)GetProcAddress(hInst,"GetInterfaceInfo"); PIP_INTERFACE_INFO pIInfo=NULL; ulSize=0; pGIInfo(pIInfo,&ulSize);//第一次调用,获取缓冲区大小 pIInfo=(PIP_INTERFACE_INFO)new(char[ulSize]); pGIInfo(pIInfo,&ulSize); //显示网络接口信息 for(int i=0;i<pIInfo->NumAdapters;i++) { cout<<"Adapter index:"<<pIInfo->Adapter[i].Index<<endl; cout<<"and name:"<<pIInfo->Adapter[i].Name<<endl; } delete pIInfo; //------------------------------------》网络接口信息部分结束 cout<<endl<<endl; //函数指针 PGIAT pGIAT; cout<<"ip information:"<<endl<<endl; //------------------------------------》IP绑定信息 pGIAT=(PGIAT)GetProcAddress(hInst,"GetIpAddrTable"); PMIB_IPADDRTABLE pIPTable=NULL; ulSize=0; pGIAT(pIPTable,&ulSize,TRUE);//获得缓冲区大小 pIPTable=(PMIB_IPADDRTABLE)new(char[ulSize]); pGIAT(pIPTable,&ulSize,TRUE); for(i=0;i<pIPTable->dwNumEntries;i++) { //取出每一个字段,显示IP cout<<"ip address:"<<(unsigned int)((LOWORD(pIPTable->table[i].dwAddr)&0x00FF))<<"."
<<(unsigned int)((LOWORD(pIPTable->table[i].dwAddr)>>8))<<"."
<<(unsigned int)((HIWORD(pIPTable->table[i].dwAddr)&0x00FF))<<"."
<<(unsigned int)((HIWORD(pIPTable->table[i].dwAddr))>>8)<<endl; //显示绑定网络接口的索引 cout<<"it is bound to interface:"<<pIPTable->table[i].dwIndex<<endl; //显示子网掩码 cout<<"it's net mask:"<<(unsigned int)((LOWORD(pIPTable->table[i].dwMask)&0x00FF))<<"."
<<(unsigned int)((LOWORD(pIPTable->table[i].dwMask)>>8))<<"."
<<(unsigned int)((HIWORD(pIPTable->table[i].dwMask)&0x00FF))<<"."
<<(unsigned int)((HIWORD(pIPTable->table[i].dwMask))>>16)<<endl; //显示广播地址 cout<<"and broadcast addres:"<<(unsigned int)((LOWORD(pIPTable->table[i].dwBCastAddr)&0x00FF))<<"."
<<(unsigned int)((LOWORD(pIPTable->table[i].dwBCastAddr)>>8))<<"."
<<(unsigned int)((HIWORD(pIPTable->table[i].dwBCastAddr)&0x00FF))<<"."
<<(unsigned int)((HIWORD(pIPTable->table[i].dwBCastAddr))>>16)<<endl; //显示最大报文大小 cout<<"it's reassembly size:"<<pIPTable->table[i].dwReasmSize<<endl; } //------------------------------------》IP绑定信息结束 PAIA pAIA; //------------------------------------》IP设置部分 if(!index) { cout<<"no adapters available, cannot set ip address!"<<endl; return 0;//没有网络接口可以设置 } pAIA=(PAIA)GetProcAddress(hInst,"AddIPAddress"); IPAddr addr=0x184BC5CA; IPMask mask=0x00FFFFFF; ULONG context; ULONG Inst; pAIA(addr,mask,index,&context,&Inst); //------------------------------------》IP设置部分结束 cout<<endl<<endl; return 0;}