我正在使用例程来收集内部IP地址,当只有一个IP地址时,它可以很好地工作。但是,在我的笔记本电脑上,它安装了VMWare Player,它有两个虚拟适配器,这些IP出现在列表中。
192.168.41.7 - 192.168.5.4 - 192.168.1.10
前两个是VMWare的虚拟适配器。我知道路由器网关是192.168.1.1。所以,如果我能以编程方式读取路由器网关,那么我可以匹配IP的第三段,以了解我所追踪的那个。
我找到了一些指向MS网站的链接以获取适配器信息,但我正在寻找一些代码片段,因为我不知道从哪里开始获取MS详细信息。
有人可以在某些网站协助或指点我。
答案 0 :(得分:2)
GetAdaptersInfo()
和GetAdaptersAddresses()
都会为每个网络适配器报告本地IP和网关。例如:
uses
..., IpTypes, IpHlpApi;
procedure GetLocalAddressesByAdaptersAddresses;
var
Ret: DWORD;
BufLen: ULONG;
Adapter, Adapters: PIP_ADAPTER_ADDRESSES;
UnicastAddr: PIP_ADAPTER_UNICAST_ADDRESS;
Gateway: PIP_ADAPTER_GATEWAY_ADDRESS;
IPAddr: string;
begin
// MSDN says:
// The recommended method of calling the GetAdaptersAddresses function is
// to pre-allocate a 15KB working buffer pointed to by the AdapterAddresses
// parameter. On typical computers, this dramatically reduces the chances
// that the GetAdaptersAddresses function returns ERROR_BUFFER_OVERFLOW,
// which would require calling GetAdaptersAddresses function multiple times.
BufLen := 1024*15;
GetMem(Adapters, BufLen);
try
repeat
// TODO: include GAA_FLAG_INCLUDE_ALL_INTERFACES on Vista+?
Ret := GetAdaptersAddresses(PF_UNSPEC, GAA_FLAG_SKIP_ANYCAST or GAA_FLAG_SKIP_MULTICAST or GAA_FLAG_SKIP_DNS_SERVER or GAA_FLAG_SKIP_FRIENDLY_NAME or GAA_FLAG_INCLUDE_GATEWAYS, nil, Adapters, BufLen);
case Ret of
ERROR_SUCCESS:
begin
// Windows CE versions earlier than 4.1 may return ERROR_SUCCESS and
// BufLen=0 if no adapter info is available, instead of returning
// ERROR_NO_DATA as documented...
if BufLen = 0 then begin
Exit;
end;
Break;
end;
ERROR_NOT_SUPPORTED:
begin
Result := False;
Exit;
end;
ERROR_NO_DATA,
ERROR_ADDRESS_NOT_ASSOCIATED:
Exit;
ERROR_BUFFER_OVERFLOW:
ReallocMem(Adapters, BufLen);
else
RaiseLastError(Ret);
end;
until False;
if Ret = ERROR_SUCCESS then
begin
Adapter := Adapters;
repeat
if (Adapter.IfType <> IF_TYPE_SOFTWARE_LOOPBACK) and
((Adapter.Flags and IP_ADAPTER_RECEIVE_ONLY) = 0) then
begin
UnicastAddr := Adapter^.FirstUnicastAddress;
while UnicastAddr <> nil do
begin
if UnicastAddr^.DadState = IpDadStatePreferred then
begin
case UnicastAddr^.Address.lpSockaddr.sin_family of
AF_INET: begin
// use PSockAddrIn(UnicastAddr^.Address.lpSockaddr)^.sin_addr as needed...
end;
AF_INET6: begin
// use PSockAddrIn6(UnicastAddr^.Address.lpSockaddr)^.sin6_addr as needed...
end;
end;
end;
UnicastAddr := UnicastAddr^.Next;
end;
Gateway := Adapter^.FirstGatewayAddress;
while Gateway <> nil do
begin
case Gateway^.Address.lpSockaddr.sin_family of
AF_INET: begin
// use PSockAddrIn(Gateway^.Address.lpSockaddr)^.sin_addr as needed...
end;
AF_INET6: begin
// use PSockAddrIn6(Gateway^.Address.lpSockaddr)^.sin6_addr as needed...
end;
end;
Gateway := Gateway^.Next;
end;
end;
Adapter := Adapter^.Next;
until Adapter = nil;
end;
finally
FreeMem(Adapters);
end;
end;
procedure GetLocalAddressesByAdaptersInfo;
var
Ret: DWORD;
BufLen: ULONG;
Adapter, Adapters: PIP_ADAPTER_INFO;
IPAddr, Gateway: PIP_ADDR_STRING;
begin
BufLen := 1024*15;
GetMem(Adapters, BufLen);
try
repeat
Ret := GetAdaptersInfo(Adapters, BufLen);
case Ret of
ERROR_SUCCESS:
begin
// Windows CE versions earlier than 4.1 may return ERROR_SUCCESS and
// BufLen=0 if no adapter info is available, instead of returning
// ERROR_NO_DATA as documented...
if BufLen = 0 then begin
Exit;
end;
Break;
end;
ERROR_NOT_SUPPORTED,
ERROR_NO_DATA:
Exit;
ERROR_BUFFER_OVERFLOW:
ReallocMem(Adapters, BufLen);
else
RaiseLastOSError(Ret);
end;
until False;
if Ret = ERROR_SUCCESS then
begin
Adapter := Adapters;
repeat
IPAddr := @(Adapter^.IpAddressList);
repeat
// use IPAddr^.IpAddress.S as needed...
IPAddr := IPAddr^.Next;
until IPAddr = nil;
Gateway := @(Adapter^.GatewayList);
repeat
// use Gateway^.IpAddress.S as needed...
Gateway := Gateway^.Next;
until Gateway = nil;
Adapter := Adapter^.Next;
until Adapter = nil;
end;
finally
FreeMem(Adapters);
end;
end;