Delphi:获取路由器的MAC

时间:2010-12-29 00:36:42

标签: delphi networking snmp indy

我正在使用Delphi,我想确定网络中网络设备的物理MAC地址,在本例中是路由器本身。

我的代码:

var
  idsnmp: tidsnmp;
  val:string;
begin
  idsnmp := tidsnmp.create;
  try
    idsnmp.QuickSend('.1.3.6.1.2.1.4.22.1.2', 'public', '10.0.0.1', val);
    showmessage(val);
  finally
    idsnmp.free;
  end;
end;

其中10.0.0.1是我的路由器。

唉,QuickSend总是发送“由#10054连接重置”。我试图修改MIB-OID,我也尝试了IP 127.0.0.1,哪个连接永远不会失败。我没有在Google上找到任何关于TIdSNMP的可用教程。 : - (

此致 丹尼尔马歇尔

2 个答案:

答案 0 :(得分:14)

您可以使用SendARP功能获取Mac地址。

检查此示例

uses
 Windows,
 WinSock,
 SysUtils;


function SendArp(DestIP,SrcIP:ULONG;pMacAddr:pointer;PhyAddrLen:pointer) : DWord; StdCall; external 'iphlpapi.dll' name 'SendARP';


function GetMacAddr(const IPAddress: string; var ErrCode : DWORD): string;
var
MacAddr    : Array[0..5] of Byte;
DestIP     : ULONG;
PhyAddrLen : ULONG;
WSAData    : TWSAData;
begin
  Result    :='';
  WSAStartup($0101, WSAData);
  try
    ZeroMemory(@MacAddr,SizeOf(MacAddr));
    DestIP    :=inet_addr(PAnsiChar(IPAddress));
    PhyAddrLen:=SizeOf(MacAddr);
    ErrCode   :=SendArp(DestIP,0,@MacAddr,@PhyAddrLen);
    if ErrCode = S_OK then
     Result:=Format('%2.2x-%2.2x-%2.2x-%2.2x-%2.2x-%2.2x',[MacAddr[0], MacAddr[1],MacAddr[2], MacAddr[3], MacAddr[4], MacAddr[5]])
  finally
    WSACleanup;
  end;
end;

答案 1 :(得分:5)

不希望窃取RRUZ的雷声,我提供了以下变体,取自我的代码库,并提供了一些观察结果。为了包含代码,我把它作为答案而非评论。

type
  TMacAddress = array [0..5] of Byte;

function inet_addr(const IPAddress: string): ULONG;
begin
  Result := ULONG(WinSock.inet_addr(PAnsiChar(AnsiString(IPAddress))));
end;

function SendARP(DestIP, SrcIP: ULONG; pMacAddr: Pointer; var PhyAddrLen: ULONG): DWORD; stdcall; external 'Iphlpapi.dll';

function GetMacAddress(const IPAddress: string): TMacAddress;
var
  MaxMacAddrLen: ULONG;
begin
  MaxMacAddrLen := SizeOf(Result);
  if SendARP(inet_addr(IPAddress), 0, @Result, MaxMacAddrLen)<>NO_ERROR then begin
    raise EMacAddressError.CreateFmt('Unable to do SendARP on address: ''%s''', [IPAddress]);
  end;
end;

有几点要做。

无需调用WSAStartup / WSACleanup。

编辑正如RRUZ在评论中指出的那样,winsock文档并没有明确地从WSAStartup / WSACleanup中免除inet_addr,因此我撤回了这一点。在Vista上,调用RtlIpv4StringToAddress更简单。说了这么多,inet_addr很容易实现,它可能更容易推出自己的。

其次,WinSock.pas中的inet_addr声明不正确。它声明返回值为u_long类型,在WinSock.pas中定义为Longint。这是带符号的4字节整数,但它应该是无符号的4字节整数ULONG。如果没有明确的强制转换,您可以获得范围错误。