Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

### Работа с MAC-адресами в Delphi: использование функции `ResolveIpNetEntry2` для извлечения MAC-адреса из кэша ARP

Delphi , Синтаксис , Справочник по API-функциям

Оригинальный заголовок

Как использовать функцию ResolveIpNetEntry2 в Delphi?

Введение

В рамках работы с сетевыми приложениями на языке Delphi зачастую возникает потребность в получении MAC-адресов устройств, находящихся в локальной сети. Для этих целей можно использовать функцию ResolveIpNetEntry2, которая позволяет извлекать информацию из кэша ARP, без необходимости отправки новых запросов ARP.

Проблема

Разработчик столкнулся с необходимостью получения MAC-адреса устройства по его IP-адресу, используя кэш ARP. После исследования он обнаружил, что функция ResolveIpNetEntry2 должна быть подходящим инструментом для решения этой задачи. Однако, не найдя примеров кода для Delphi и соответствующих заголовков, разработчик попытался самостоятельно выполнить перевод функций и типов данных, что в итоге привело к ошибке ERROR_INVALID_PARAMETER (код 87).

Решение

В соответствии с документацией ResolveIpNetEntry2, ошибка ERROR_INVALID_PARAMETER может быть вызвана неправильным параметром, переданным в функцию. Это может быть NULL- указатель, неверно установленный адрес, неопределенные значения полей структуры MIB_IPNET_ROW2 или передача адреса петлирования. Перевод структур API был выполнен некорректно, особенно в части поля Address, которое должно быть записано внутри структуры MIB_IPNET_ROW2, а не быть внешним указателем. Также были допущены ошибки при выделении памяти и инициализации блоков памяти.

Исправленный код

Для корректной работы с ResolveIpNetEntry2 необходимо правильно определить структуры данных и обработать входные параметры. Ниже приведен пример кода, который демонстрирует, как можно использовать ResolveIpNetEntry2 для получения MAC-адреса по IP-адресу устройства в локальной сети:

{$MINENUMSIZE 4}

const
  IF_MAX_PHYS_ADDRESS_LENGTH = 32;

type
  NET_LUID_INFO = record
    Reserved: array [0..2] of UCHAR;
    NetLuidIndex: array [0..2] of UCHAR;
    IfType: array [0..1] of UCHAR;
  end;

  NET_LUID = record
    case Integer of
      0: (Value: UInt64);
      1: (Info: NET_LUID_INFO);
  end;

  NL_NEIGHBOR_STATE = (
    NlnsUnreachable = 0,
    NlnsIncomplete,
    NlnsProbe,
    NlnsDelay,
    NlnsStale,
    NlnsReachable,
    NlnsPermanent,
    NlnsMaximum);

  PSOCKADDR_INET = ^SOCKADDR_INET;
  SOCKADDR_INET = record
    case Integer of
      0: (Ipv4: SOCKADDR_IN);
      1: (Ipv6: SOCKADDR_IN6);
      2: (si_family: ADDRESS_FAMILY);
  end;

  NETIO_STATUS = DWORD;
  NET_IFINDEX = ULONG;

  PMIB_IPNET_ROW2 = ^MIB_IPNET_ROW2;
  MIB_IPNET_ROW2 = record
    Address: SOCKADDR_INET;
    InterfaceIndex: NET_IFINDEX;
    InterfaceLuid: NET_LUID;
    PhysicalAddress: array [0..IF_MAX_PHYS_ADDRESS_LENGTH - 1] of UCHAR;
    PhysicalAddressLength: ULONG;
    State: NL_NEIGHBOR_STATE;
    Flags: UCHAR;
    ReachabilityTime: record
      case Integer of
        0: (LastReachable: ULONG);
        1: (LastUnreachable: ULONG);
      end;
    function IsRouter: Boolean;
    function IsUnreachable;
  end;

function MIB_IPNET_ROW2.IsRouter: Boolean;
begin
  Result := (Flags and $01) <> 0;
end;

function MIB_IPNET_ROW2.IsUnreachable;
begin
  Result := (Flags and $02) <> 0;
end;

function ResolveIp(const AIp: String; AIfIndex: ULONG): String;
type
  TResolveIpNetEntry2Func = function (Row: PMIB_IPNET_ROW2; const SourceAddress: PSOCKADDR_INET): NETIO_STATUS; stdcall;
const
  IphlpApiDll = 'iphlpapi.dll';
var
  hIphlpApiDll: THandle;
  ResolveIpNetEntry2: TResolveIpNetEntry2Func;
  status: NETIO_STATUS;
  Row: PMIB_IPNET_ROW2;
begin
  Result := '';
  hIphlpApiDll := LoadLibrary(IphlpApiDll);
  if hIphlpApiDll = 0 then
    Exit;

  try
    ResolveIpNetEntry2 := GetProcAddress(hIphlpApiDll, 'ResolveIpNetEntry2');
    if not Assigned(ResolveIpNetEntry2) then
      Exit;

    SetLength(Row, SizeOf(MIB_IPNET_ROW2));
    ZeroMemory(@Row[0], SizeOf(MIB_IPNET_ROW2));

    if InetPton(AF_INET, PChar(AIp), @(Row.Address.Ipv4.sin_addr)) = 1 then
      Row.Address.Ipv4.sin_family := AF_INET
    else
    if InetPton(AF_INET6, PChar(AIp), @(Row.Address.Ipv6.sin6_addr)) = 1 then
      Row.Address.Ipv6.sin6_family := AF_INET6
    else
      Exit;

    Row.InterfaceIndex := AIfIndex;

    status := ResolveIpNetEntry2(@Row, nil);
    // ...
  finally
    FreeLibrary(hIphlpApiDll);
  end;
end;

Альтернативный метод

Также возможно использовать функцию ResolveIp без динамического выделения памяти для Row:

function ResolveIp(const AIp: String; AIfIndex: ULONG): String;
var
  Row: MIB_IPNET_ROW2;
begin
  // ...
  ZeroMemory(@Row, SizeOf(Row));
  // ...
  status := ResolveIpNetEntry2(@Row, nil);
  // ...
end;

В этом случае Row является локальной переменной на стеке, и его содержимое инициализируется нулями. Важно различать обращение к локальной переменной и к динамически выделенной памяти.

Заключение

Использование функции ResolveIpNetEntry2 позволяет извлекать MAC-адреса устройств из кэша ARP, что может быть полезно для различных сетевых приложений на Delphi. Важно правильно определить структуры данных и обработать входные параметры для корректной работы функции.

Создано по материалам из источника по ссылке.

Описание Context: Запрос на использование функции `ResolveIpNetEntry2` в Delphi для получения MAC-адреса устройства по его IP-адресу.


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.


:: Главная :: Справочник по API-функциям ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-12-22 20:14:06
2024-12-26 14:45:25/0.0034401416778564/0