获取IP地址以及全部TCPIP连接的掩码
问题提出/摘要:我们有很多种方法获取一台计算机的IP地址,但这里才是“正确”的方法:列出所有的地址、网络掩码、广播地址和连接状态等,包括环回点 127.0.0.1。需要使用到WinSock2。   回答:  这是一个完整的Delphi单元,将它加入到你的工程中,你可以调用:    EnumInterfaces(var s string): Boolean;     来返回所有IP地址、网络掩码、广播地址和连接状态。  --------------------------------------------------------------------     unit USock;     interface     uses Windows, Winsock;     {     此函数列举出所有的TCP/IP连接,并返回一个由回车换行(CRLF)符分隔的字符串,包含以下信息:    IP, NetMask, BroadCast-Address, Up/Down status,   Broadcast support, Loopback     如果你将这个字符串赋给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;     { 从Winsock 2.0导入函数WSAIOCtl -- 在Win98/ME/2K and 95 OSR2, NT srv pack #3下才有Winsock 2 }    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';     { Constants taken from C header files }     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; // Interface flags   iiAddress: sockaddr_gen; // Interface address   iiBroadcastAddress: sockaddr_gen; // Broadcast address   iiNetmask: sockaddr_gen; // Network mask   end;     implementation     {-------------------------------------------------------------------     1. 打开Winsock  2. 创建一个socket  3. 调用WSAIOCtl获取网络连接  4. 对每个连接,获取它的IP、掩码、广播地址、状态  5. 将信息填充到一个由CDLF分隔的字符串中  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; // Initialize   sInt := '';     WSAStartup($0101, wsaD); // Start WinSock   // You should normally check   // for errors here :)     s := Socket(AF_INET, SOCK_STREAM, 0); // Open a socket   if (s = INVALID_SOCKET) then exit;     try // Call WSAIoCtl   PtrA := @bytesReturned;   if (WSAIoCtl(s, SIO_GET_INTERFACE_LIST, nil, 0, @Buffer, 1024, PtrA, nil,   nil)   <> SOCKET_ERROR)   then   begin // If ok, find out how   // many interfaces exist     NumInterfaces := BytesReturned div SizeOf(INTERFACE_INFO);     for i := 0 to NumInterfaces - 1 do // For every interface   begin   pAddrInet := Buffer[i].iiAddress.addressIn; // IP ADDRESS   pAddrString := inet_ntoa(pAddrInet.sin_addr);   sInt := sInt + ' IP=' + pAddrString + ',';   pAddrInet := Buffer[i].iiNetMask.addressIn; // SUBNET MASK   pAddrString := inet_ntoa(pAddrInet.sin_addr);   sInt := sInt + ' Mask=' + pAddrString + ',';   pAddrInet := Buffer[i].iiBroadCastAddress.addressIn; // Broadcast addr   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,' // Interface up/down   else   sInt := sInt + ' Interface DOWN,';     if (SetFlags and IFF_BROADCAST) = IFF_BROADCAST then // Broadcasts   sInt := sInt + ' Broadcasts supported,' // supported or   else // not supported   sInt := sInt + ' Broadcasts NOT supported,';     if (SetFlags and IFF_LOOPBACK) = IFF_LOOPBACK then // Loopback or   sInt := sInt + ' Loopback interface'   else   sInt := sInt + ' Network interface'; // normal     sInt := sInt + #13#10; // CRLF between   // each interface   end;   end;   except   end;   //   // Close sockets   //   CloseSocket(s);   WSACleanUp;   result := false;   end;     end.