Delphi:获取路由器的MAC

Delphi:获取路由器的MAC,delphi,networking,snmp,indy,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;

我正在使用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,该连接永远不会失败。我在谷歌上找不到任何关于TIDSMP的有用教程:-(

问候 Daniel Marschall

您可以使用该函数获取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;

我不想抢走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;
类型
TMacAddress=字节数组[0..5];
函数inet_addr(const-IPAddress:string):ULONG;
开始
结果:=ULONG(WinSock.inet_addr(PAnsiChar(AnsiString(IPAddress)));
结束;
函数SendARP(DestIP,SrcIP:ULONG;pMacAddr:Pointer;var PhyAddrLen:ULONG):DWORD;stdcall;外部“iphlapi.dll”;
函数GetMacAddress(常量IPAddress:string):TMacAddress;
变量
马克斯马卡德伦:乌龙;
开始
MaxMacAddressLen:=SizeOf(结果);
如果SendARP(inet_addr(IPAddress),0,@Result,MaxMacAddrLen)没有错误,那么开始
raise EMACADDRESERROR.CreateFmt('无法对地址:'%s'',[IPAddress]执行SendARP操作];
结束;
结束;
有几点需要说明

无需调用WSAStartup/WSACleanup

编辑正如RRUZ在评论中指出的,winsock文档并没有明确地将inet_addr从WSAStartup/WSACleanup中豁免,所以我收回这一点。在Vista上,只需调用RtlIpv4StringToAddress就更简单了。尽管如此,inet_addr实现起来非常简单,您自己的实现起来可能更容易


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

Indy太糟糕了,10054与TCP相关。Me另外,你已经有了10.0.0.1的ARP记录,使用IP Helper API进行查询。Indy其实没那么糟糕,你必须处理异常…尝试…除了任何人?!我最近发现的另一件事是,即使你处理异常,有时如果你安装了eureka日志,仍然会引发#10054异常,你可以解决通过为EIdSocket错误或类似的东西添加异常过滤器来实现这一点…没有更多的异常,一切都可以完美地工作!!@Dorin Duminica:10054表示代理主机使用TCP RST或ICMP Unrach重新打印的内容。总之,Indy过去使用异常进行流控制,这就是为什么一些无意义的错误会不时出现在Indy的深处。@user205376 yes 10054在客户端因应用程序崩溃或连接丢失而断开连接时出现,但这很容易处理…您是否检查了路由器的SNMP配置?您的参数是否正确?是否有防火墙可以阻止SNMP通信?非常感谢!您在代码方面帮了我很多忙。:-)我已经开始阅读MSDN中的IP Helper参考资料,但我不知道SendARP()可以完成这项工作。+1 RRUZ在他的博客上看到了很多关于互联网的东西:-)干得好@Daniel Marschall,是的,谢天谢地SendARP不会发送任何东西,而是返回已知的MACMy代码库使用相同的方法。请注意,我认为WSAStartup调用不是必需的。我也不信任在字符串上使用PAnsiChar()。在UNICODE Delphi中,它不应该是PAnsiChar(ansisting())?为了方便起见,请参阅JWAIPHLAPI,我们在其中转换了此DLL中的所有函数。@David,
EMacAddressError
exception类的声明在哪里?@RRUZ EMacAddressError=class(exception);(或者随便你怎么想)@RRUZ我想你是因为缺少WSAStartup而给了我否决票。事实上,我可能同意你的看法。最好始终遵循官方文件。在Vista上,我认为RtlIpv4StringToAddress是一个不错的选择。@RRUZ好吧,我认为这是值得的,即使它不是你写的。总是很高兴得到一个反对票的解释,请注意。@user205376呃,你在说什么?到底什么是不好的?!