Sources
Delphi Russian Knowledge Base
DRKB - это самая большая и удобная в использовании база знаний по Дельфи в рунете, составленная Виталием Невзоровым

Получение IP-адреса и маски для всех сетевых интерфейсов

01.01.2007

Автор: Giannis Sampaziotis

Существует множество методов получения IP адреса компьютера. Но данный пример представляет наиболее корректный способ получения всех адресов, сетевых масок, broadcast адресов и статусов для всех интерфейсов включая циклический 127.0.0.1 - требует WinSock 2.

Совместимость: Delphi 3.х (или выше)

Это завершённый Delphi компонент. Для его использования достаточно вызвать :

  EnumInterfaces(var s string): Boolean;

которая вернёт строку, разделённую CRLF и содержащую всё, нужную нам информацию.

unit USock; 
 
interface
 
uses
Windows, Winsock;
 
{
 
 
Если Вы поместите строку результатов в wide TMEMO его свойство memo.lines.text)
 
то никаких результатов не увидите.
 
 
Тестировалось на Win98/ME/2K, 95 OSR 2 и NT service
  pack
#3 , потому что используется WinSock 2 (WS2_32.DLL)
 
}
 
function EnumInterfaces(var sInt: string): Boolean;
 
{ функция WSAIOCtl импортируется из Winsock 2.0 - Winsock 2 доступен }
{ только в Win98/ME/2K и 95 OSR2, NT srv pack #3 }
 
function WSAIoctl(s: TSocket; cmd: DWORD; lpInBuffer: PCHAR; dwInBufferLen:
  DWORD
;
  lpOutBuffer
: PCHAR; dwOutBufferLen: DWORD;
  lpdwOutBytesReturned
: LPDWORD;
  lpOverLapped
: POINTER;
  lpOverLappedRoutine
: POINTER): Integer; stdcall; external 'WS2_32.DLL';
 
{ Константы взятые из заголовка C файлов }
 
const SIO_GET_INTERFACE_LIST = $4004747F;
  IFF_UP
= $00000001;
  IFF_BROADCAST
= $00000002;
  IFF_LOOPBACK
= $00000004;
  IFF_POINTTOPOINT
= $00000008;
  IFF_MULTICAST
= $00000010;
 
type sockaddr_gen
= packed record
   
AddressIn: sockaddr_in;
    filler
: packed array[0..7] of char;
 
end;
 
type INTERFACE_INFO
= packed record
    iiFlags
: u_long; // Флаги интерфейса
    iiAddress
: sockaddr_gen; // Адрес интерфейса
    iiBroadcastAddress
: sockaddr_gen; // Broadcast адрес
    iiNetmask
: sockaddr_gen; // Маска подсети
 
end;
 
implementation
 
{-------------------------------------------------------------------
 
1. Открываем WINSOCK
2. Создаём сокет
3. Вызываем WSAIOCtl для доступа к сетевым интерфейсам
4. Для каждого интерфейса, получаем IP, MASK, BROADCAST, статус
5. Разделяем строку символом CRLF  
6. Конец :)
 
--------------------------------------------------------------------}
 
function EnumInterfaces(var sInt: string): Boolean;
var s: TSocket;
  wsaD
: WSADATA;
 
NumInterfaces: Integer;
 
BytesReturned, SetFlags: u_long;
  pAddrInet
: SOCKADDR_IN;
  pAddrString
: PCHAR;
 
PtrA: pointer;
 
Buffer: array[0..20] of INTERFACE_INFO;
  i
: Integer;
begin
  result
:= true;                                // Инициализируем переменную
  sInt
:= '';
 
 
WSAStartup($0101, wsaD);                      // Запускаем WinSock
                                               
// Здесь можно дабавить различные обработчики ошибки :)
 
  s
:= Socket(AF_INET, SOCK_STREAM, 0);          // Открываем сокет
 
if (s = INVALID_SOCKET) then exit;
 
 
try                                            // Вызываем WSAIoCtl
   
PtrA := @bytesReturned;
   
if (WSAIoCtl(s, SIO_GET_INTERFACE_LIST, nil, 0, @Buffer, 1024, PtrA, nil,
     
nil)
     
<> SOCKET_ERROR)
     
then
   
begin                                        // Если OK, то определяем количество существующих интерфейсов
 
     
NumInterfaces := BytesReturned div SizeOf(INTERFACE_INFO);
 
     
for i := 0 to NumInterfaces - 1 do        // Для каждого интерфейса
     
begin
        pAddrInet
:= Buffer[i].iiAddress.addressIn;            // IP адрес
        pAddrString
:= inet_ntoa(pAddrInet.sin_addr);
        sInt
:= sInt + ' IP=' + pAddrString + ',';
        pAddrInet
:= Buffer[i].iiNetMask.addressIn;            // Маска подсети
        pAddrString
:= inet_ntoa(pAddrInet.sin_addr);
        sInt
:= sInt + ' Mask=' + pAddrString + ',';
        pAddrInet
:= Buffer[i].iiBroadCastAddress.addressIn;  // Broadcast адрес
        pAddrString
:= inet_ntoa(pAddrInet.sin_addr);
        sInt
:= sInt + ' Broadcast=' +  pAddrString + ',';
 
       
SetFlags := Buffer[i].iiFlags;
       
if (SetFlags and IFF_UP) = IFF_UP then
          sInt
:= sInt + ' Interface UP,'                    // Статус интерфейса up/down
       
else
          sInt
:= sInt + ' Interface DOWN,';
 
       
if (SetFlags and IFF_BROADCAST) = IFF_BROADCAST then  // Broadcasts
          sInt
:= sInt + ' Broadcasts supported,'              // поддерживает или
       
else                                                  // не поддерживается
          sInt
:= sInt + ' Broadcasts NOT supported,';
 
       
if (SetFlags and IFF_LOOPBACK) = IFF_LOOPBACK then    // Циклический или
          sInt
:= sInt + ' Loopback interface'
       
else
          sInt
:= sInt + ' Network interface';                  // нормальный
 
        sInt
:= sInt + #13#10;                                // CRLF между каждым интерфейсом
     
end;
   
end;
 
except
 
end;
//
// Закрываем сокеты
//
 
CloseSocket(s);
 
WSACleanUp;
  result
:= false;
end;
 
end.

Взято из https://forum.sources.ru