Delphi:获取路由器的MAC

发布于 2024-10-09 12:16:49 字数 491 浏览 4 评论 0原文

我正在使用 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 总是发送“Connection Reset by Peer #10054”。我尝试修改 MIB-OID,还尝试了 IP 127.0.0.1,该连接永远不会失败。我在 Google 上没有找到任何关于 TIdSNMP 的可用教程。 :-(

问候 丹尼尔·马歇尔

I am using Delphi and I want to determinate the physical MAC address of a network device in my network, in this case the Router itself.

My code:

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;

where 10.0.0.1 is my router.

Alas, QuickSend does always send "Connection reset by peer #10054". I tried to modify the MIB-OID and I also tried the IP 127.0.0.1 which connection should never fail. I did not find any useable Tutorials about TIdSNMP at Google. :-(

Regards
Daniel Marschall

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

绮烟 2024-10-16 12:16:49

您可以使用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(AnsiString(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;

You can use the SendARP function to get the Mac Address.

check this sample

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(AnsiString(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;
浅笑轻吟梦一曲 2024-10-16 12:16:49

不想抢 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 文档没有明确将 inet_addr 从 WSAStartup/WSACleanup 中排除,因此我撤回这一点。在 Vista 上,调用 RtlIpv4StringToAddress 更简单。话虽如此,inet_addr 非常容易实现,您自己的实现可能会更容易。

其次WinSock.pas中inet_addr的声明不正确。它将返回值声明为 u_long 类型,该类型在 WinSock.pas 中定义为 Longint。这是一个有符号 4 字节整数,但它应该是一个无符号 4 字节整数 ULONG。如果没有显式转换,您可能会遇到范围错误。

Not wishing to steal the thunder of RRUZ, I offer the following variant, taken from my codebase, with some observations. I've done this as an answer rather than a comment in order to include code.

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;

There are a couple of points to make.

There is no need to call WSAStartup/WSACleanup.

EDIT As RRUZ points out in a comment, the winsock documentation does not explictly exempt inet_addr from WSAStartup/WSACleanup so I retract this point. On Vista it is simpler just to call RtlIpv4StringToAddress. Having said all that, inet_addr is so easy to implement it may just be easier to roll your own.

Secondly the declaration of inet_addr in WinSock.pas is incorrect. It declares the return value to be of a type u_long which is defined in WinSock.pas as Longint. This is a signed 4 byte integer but it should be an unsigned 4 byte integer, ULONG. Without the explicit cast you can get range errors.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文