如何在Delphi中提取本地计算机站点本地和链接本地IPv6地址?

时间:2013-02-28 09:56:49

标签: delphi

我目前正在尝试开发一个显示IPv6流量的应用程序。我很困惑如何提取本地站点的本地和本地机器的链接本地地址。任何指导将不胜感激。

我正在使用的delphi中的IPv6数据包的结构是:

type
 PIPV6HeaderPtr = ^TIPV6Header;
 TIPV6Header = packed record
 ip6_flow       : DWORD;    // 4  bits = version #,// 8  bits = Trafic class,// 20 bits = flow label
ip6_len        : Word;//Cardinal;    // Payload length
//ip6_next       : Cardinal;    // Next Header
  ip6_next       : Byte;    // Next Header
ip6_hops       : Byte;         // Hop Limit
  h_source  : IN6_ADDR;
 h_dest    : IN6_ADDR;
end;

//
// IPv6 extension header format
//
 type
  PIPV6EXTPTR = ^TIPV6EXT;
  TIPV6EXT = packed record
  ip6_next       : Byte;
  ip6_len        : Byte;
  ip6_data       : array[0..1] of Byte;

End;


 type
    PIPV6EXT_FRAGPTR = ^TIPV6EXT_FRAG;
    TIPV6EXT_FRAG    = packed record
    ip6_next       : Byte;
   ip6_reserved   : Byte;
   ip6_offlg      : Word;
   ip6_ident      : DWORD;
 End;

提前致谢。

2 个答案:

答案 0 :(得分:3)

请参阅以下有关站点本地地址和链接本地地址以及它们如何工作的说明:

IPv6 tutorial – Part 6: Site-local addresses and link-local addresses

您可以使用Win32 API GetAdapterAddresses()函数获取本地计算机的IPv6地址。

答案 1 :(得分:0)

我找到了另一种使用WSAIoctl获取地址的方法。我在下面添加我的代码。

使用WinSock2; //在网上广泛提供

   function TForm1.GetIPUsingIoctlMethod(var sInt: string): Boolean;
   var
     s: TSocket;
     wsaD: TWSADATA;
     NumInterfaces: Integer;
     BytesReturned, SetFlags: u_long;
     pAddrInet: SOCKADDR_IN;
     pAddrString: PCHAR;
     PtrA: pointer;
     Buffer: Array[0..20] Of  INTERFACE_INFO_EX;
     i: Integer;
     Local_IpList : TStringList ;
     addrList : LPSOCKET_ADDRESS_LIST ;
     in6 :  PSockAddr;
     protoInfo : WSAProtocol_Info;
     text : Array[1..46] Of Char;
     Buffer1 : DWORD;
     Str : String;

 begin
      result := False;                               // Initialize
      sInt := '';
Try

    WSAStartup($0101, wsaD);                      // Start WinSock
                                                  // You should normally check
                                                  // for errors here :)

    {Create a WSA Socket}
    //s := WSASocketA(AF_INET6,SOCK_STREAM, IPPROTO_IP, nil, 0, 0);

    s:= Socket(AF_INET6,SOCK_STREAM,IPPROTO_IP);

    //s := Socket(AF_INET6, SOCK_STREAM, 0);         // Open a socket
    if (s = INVALID_SOCKET) then exit;

    try                                           // Call WSAIoCtl
      PtrA := @bytesReturned;

      if (WSAIoCtl(s, SIO_ADDRESS_LIST_QUERY, nil, 0, @Buffer, SizeOf(Buffer), PtrA, nil, nil)<> SOCKET_ERROR)
        then
          begin                                       // If ok, find out how
                                                   // many interfaces exist

                Result   := True;
                addrList := LPSOCKET_ADDRESS_LIST(@Buffer);


                DebugLog(' i = ' + IntToStr(addrList.iAddressCount),0);
               // NumInterfaces := BytesReturned div SizeOf(INTERFACE_INFO);

                Local_IpList := TStringList.Create ;
                for i := 0 to addrList.iAddressCount - 1 do        // For every interface
                begin
                   If ( addrList.Address[i].lpSockaddr.sin_family = AF_Inet6) Then
                   Begin
                      in6 := PSockaddr(@addrList.Address[i].lpSockaddr);
                      Buffer1 := SizeOf(Text);
                      //protoInfo.
                      FillChar(Text,SizeOf(Text),#0);
                      If WSAAddressToString(addrList.Address[i].lpSockaddr,addrList.Address[i].iSockaddrLength,
                                          nil,@text,Buffer1) <> 0 Then
                      Begin
                          debuglog('err1 = ' + SysErrorMessage(WSAGetLastError),0);
                      end;
                      Str := Text;
                      DebugLog(' Addr cnt =' + IntToStr(i) + ' = ' + Str,0);
                      Buffer1 := 0;
                      FillChar(Text,SizeOf(Text),#0);
                      //in6.
                      //DebugLog('ip = ' + );
                      //IN6_IS_ADDR_LINKLOCAL
                   end;
                end;

      end
      Else
          sInt := SysErrorMessage(WSAGetLastError);
    except
    end;
  //
  // Close sockets
  //
    CloseSocket(s);
    WSACleanUp;
 Except
 End;

端;

debugLog只是一种在文本文件中写入的方法。