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

Существует множество методов получения 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.
Author: Giannis Sampaziotis
Source: http://forum.sources.ru
ID: 03346
Category:Связь