2014-01-30 8 views
0

델파이 소켓 프로그래밍을위한 IPv6 가용성을 자동 감지하고보고하려고합니다.잘못된 IP 주소 받기

"localhost"의 경우 다음 코드는 IPv6의 경우 "1700 ::"을, IPv4의 경우 "2.0.0.0"을 반환합니다. 이 주소는 간단한 테스트 용이며 내 컴퓨터에 대해 1 또는 127.0.0.1을 반환해야합니다. 나는 "localhost"를 다양한 IP 주소로 변환하려고 할 때 잘못하고있는 것을 알아 내려고 노력하고 있으므로 호출 코드에서 소켓 API 오류가 발생하지는 않습니다. Indy 헤더를 사용하고 있습니다.

TLSocketAddress = record 
    case Integer of 
    AF_INET: 
     (IPv4: TSockAddrIn); 
    AF_INET6: 
     (IPv6: TSockAddrIn6); 
end; 

TLIpInfo = record 
private 
    function GetFamily: TProtocolFamily; 
public 
    Address : TLSocketAddress; 
    HostName: string; 
    Machine: string; 
    IP6 : string; 
    IP4 : string; 
    Port : integer; 
    Error : integer; 
    property Family : TProtocolFamily read GetFamily; 
end; 

및 검색 루틴은 다음과 같습니다 :

유형 선언은 내가 너무 늦게 작성자 수 있습니다 알고

function GetIpInfo(
    const AHostName : string; 
    const APort  : integer 
): TLIpInfo; 
var 
    nameRet : PAnsiChar; 
    ptr  : Pointer; 
    Hints  : TAddrInfoW; 
    AddrInfo : PAddrInfoW; 
    NextInfo : PAddrInfoW; 
    RetVal : Integer; 
    ip, 
    machine : string; 
    namelen : integer; 
begin 
    ZeroMemory(@Result, SizeOf(Result)); 
    FillChar(Hints, SizeOf(Hints), 0); 
    Hints.ai_family := AF_UNSPEC; 

    AddrInfo := nil; 
    RetVal := GetAddrInfo(PWideChar(AHostName), nil, @Hints, @AddrInfo); 
    if RetVal = 0 then 
    try 
    Result.HostName := AHostName; 
    Result.Port := APort; 
    NextInfo := AddrInfo; 
    while NextInfo <> nil do 
    begin 
     if (NextInfo.ai_family = AF_INET) or (NextInfo.ai_family = AF_INET6) then 
     begin 
     if (Result.Machine = '') then 
     begin 
      SetLength(machine, NI_MAXHOST); 
      RetVal := GetNameInfo(NextInfo.ai_addr, NextInfo.ai_addrlen, 
      PChar(machine), NI_MAXHOST, nil, 0, 0); 
      if (RetVal <> 0) then 
      begin 
      NextInfo := NextInfo.ai_next; 
      continue; 
      end; 
      Result.Machine := PChar(machine); 
     end; 

     if NextInfo.ai_family = AF_INET then 
     begin 
      ptr := PSockAddrIn(NextInfo.ai_addr); 
      namelen := INET_ADDRSTRLEN; 
      SetLength(ip, namelen); 
     end 
     else 
     begin 
      ptr := PSockAddrIn6(NextInfo.ai_addr); 
      namelen := INET6_ADDRSTRLEN; 
      SetLength(ip, namelen); 
     end; 

     nameRet := inet_ntop(NextInfo.ai_family, ptr, PChar(ip), namelen); 
     if (nameRet = nil) then 
     begin 
      NextInfo := NextInfo.ai_next; 
      continue; 
     end; 

     if (NextInfo.ai_family = AF_INET6) then 
      Result.IP6 := PChar(ip) 
     else 
      Result.IP4 := PChar(ip); 
     end; 
     NextInfo := NextInfo.ai_next; 
    end; 
    finally 
    FreeAddrInfo(AddrInfo); 
    end; 
end; 
+1

? '/ etc/hosts', DNS 등에서 설정할 수 있습니다. –

+1

사실 누군가는 LocalHost가 –

+0

을 원하면'8.8.8.8 '을 가리 키도록 설정할 수 있습니다. 또한 도메인에 있다면' localhost.example.com'을 사용하면'localhost.'를 시도 할 수 있습니다. –

답변

1

,하지만 난 같은 문제로 오늘 고투하고 발견 ADDRINFO 구조체에 대한 포인터를 inet_ntop으로 전달하지만 포인터는 바이너리 주소에만 전달해야합니다.
그래서해야 IPv4의 주소를 intet_ntop 에 전화 :

inet_ntop(NextInfo.ai_family, @PSockAddrIn(NextInfo.ai_addr).sin_addr, PChar(ip), namelen) 

IPv6를에 대한

는해야한다 : 당신은 왜 "localhost"를 조회하려고

inet_ntop(NextInfo.ai_family, @PSockAddrIn6(NextInfo.ai_addr).sin6_addr, PChar(ip), namelen) 
+0

후속 조치 주셔서 감사! 내가 요청한 이후로 오랜 시간이 지났지 만 해결되었지만 계약에 따라 코드가 작성되어 더 이상 액세스 할 수 없습니다. 너는 위대한 탐정 작업을 했어. 나는 똑같은 것을 알아 채고 그것을 고치기 시작했다. –