【发布时间】:2016-11-14 17:49:31
【问题描述】:
我想从同一本地网络中主机的 IP 获取 MAC 地址。我宁愿从本地缓存中获取此信息,而不是发送新的 ARP ARP 请求。我发现ResolveIpNetEntry2 应该是我需要的。
不幸的是,我没有找到任何具有该功能的 Delphi 代码示例。更糟糕的是,我什至没有找到该函数及其数据类型的任何 Delphi 标头。所以我尝试自己转换它们。好吧,它编译了,但我得到 ERROR_INVALID_PARAMETER (87),所以显然我转换了一些错误。
谁能告诉我如何改正它?
const
IF_MAX_PHYS_ADDRESS_LENGTH = 32;
type
NET_LUID = record
case Word of
1: (Value: Int64;);
2: (Reserved: Int64;);
3: (NetLuidIndex: Int64;);
4: (IfType: Int64;);
end;
NL_NEIGHBOR_STATE = (
NlnsUnreachable=0,
NlnsIncomplete,
NlnsProbe,
NlnsDelay,
NlnsStale,
NlnsReachable,
NlnsPermanent,
NlnsMaximum);
PMIB_IPNET_ROW2 = ^MIB_IPNET_ROW2;
MIB_IPNET_ROW2 = record
Address: LPSOCKADDR; //SOCKADDR_INET
InterfaceIndex: ULONG; //NET_IFINDEX
InterfaceLuid: NET_LUID;
PhysicalAddress: array [0..IF_MAX_PHYS_ADDRESS_LENGTH - 1] of UCHAR;
PhysicalAddressLength: ULONG;
State: NL_NEIGHBOR_STATE;
Union: record
case Integer of
0: (IsRouter: Boolean;
IsUnreachable: Boolean);
1: (Flags: UCHAR);
end;
ReachabilityTime: record
case Integer of
0: (LastReachable: ULONG);
1: (LastUnreachable: ULONG);
end;
end;
function ResolveIp(const AIp: String; AIfIndex: ULONG): String;
type
TResolveIpNetEntry2Func = function (Row: PMIB_IPNET_ROW2; const SourceAddress: LPSOCKADDR): DWORD; stdcall; //NETIOAPI_API
const
IphlpApiDll = 'iphlpapi.dll';
var
hIphlpApiDll: THandle;
ResolveIpNetEntry2: TResolveIpNetEntry2Func;
dw: DWORD;
Row: PMIB_IPNET_ROW2;
SourceAddress: LPSOCKADDR;
IpAddress: LPSOCKADDR;
begin
hIphlpApiDll := LoadLibrary(IphlpApiDll);
if hIphlpApiDll = 0 then
Exit;
ResolveIpNetEntry2 := GetProcAddress(hIphlpApiDll, 'ResolveIpNetEntry2');
if (@ResolveIpNetEntry2 = nil) then
Exit;
IpAddress := AllocMem(SizeOf(IpAddress));
IpAddress.sa_family := AF_INET;
IpAddress.sa_data := PAnsiChar(AIp);
Row := AllocMem(SizeOf(Row));
Row.Address := IpAddress;
Row.InterfaceIndex := AIfIndex;
SourceAddress := 0;
dw := ResolveIpNetEntry2(Row, SourceAddress);
//...
end;
【问题讨论】:
-
为什么不直接获取 ARP -A IPNUMBER 输出并从中提取 MAC 地址?
-
这里你可以看到一个如何捕捉ARP命令stackoverflow.com/questions/9119999/…的输出的例子
-
我知道如何通过命令行发送 ARP 请求,甚至更好地通过 API (SendArp())。在这种情况下,出于多种原因,我更喜欢获取缓存信息而不是发送新请求。
-
建议的 ARP -A 命令返回缓存的内容。 technet.microsoft.com/en-us/library/cc940107.aspx
-
你是对的:arp.exe 执行缓存查找而不是发送新查找。但最后它只是在内部执行一些 API 调用,很可能是 ResolveIpNetEntry2。我总是更喜欢直接使用 API 而不是解析命令行输出。