Delphi: получить MAC маршрутизатора
Я использую 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 всегда отправляет "сброс соединения peer #10054". Я попытался изменить MIB-OID, и я также попробовал IP 127.0.0.1, соединение которого никогда не должно завершиться неудачей. Я не нашел никаких полезных учебников о TIdSNMP в Google. :-(
С уважением Дэниел Маршалл!--2-->
2 ответов
можно использовать 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(01, 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;
есть пара моментов.
нет необходимости вызывать WSAStartup / WSACleanup.
редактировать как указывает RRUZ в комментарии, документация winsock не явно освобождает inet_addr от WSAStartup/WSACleanup поэтому я беру свои слова обратно. На Vista проще просто вызвать RtlIpv4StringToAddress. Сказав Все это, inet_addr настолько легко реализовать, что может быть проще свернуть свой собственный.
во-вторых, объявление inet_addr в WinSock.пас неверен. Он объявляет возвращаемое значение типа u_long, который определен в WinSock.ССА как добавлены типы longint. Это целое число со знаком 4 байта, но оно должно быть целым числом без знака 4 байта, ULONG. Без явного приведения вы можете получить range ошибки.