Delphi中的IP地址字符串例程?

Jer*_*dge 2 delphi string ip-address delphi-7

我正在寻找Delphi中验证和操作IP地址的方法.它应该能做的一些事情是......

  • 验证字符串是否是有效的IP地址
  • 验证字符串是否是有效的子网掩码
  • 验证IP地址是否在给定的子网中
  • 某些类型(记录或字符串或其他)用于存储IP地址
  • IP地址类型的基本转换,例如StringArray[0..3] of Byte
  • 任何其他IP地址例程,可以使IP操作更容易

基本原因是我希望在继续前进之前看看这些东西是否已经存在并重新发明.

NGL*_*GLN 8

我曾经写过一个IPv4和IPv6转换单元,包括两种类型IP地址的自定义变体类型.这个答案显示了其功能的一些例子.最初,它被设计为在某些滑块控件1)上按比例显示各种类型的值.然后要求默认现有的库是不够的,但我同意这里的评论,你可能会得到Indy(10!)或类似的帮助.

使用该单元的几个代码段回答您的问题列表:

  • Q4:IP类型的存储类型:

    const
      IPv4BitSize = SizeOf(Byte) * 4 * 8;
      IPv6BitSize = SizeOf(Word) * 8 * 8;
    
    type
      T4 = 0..3;
      T8 = 0..7;
      TIPv4ByteArray = array[T4] of Byte;
      TIPv6WordArray = array[T8] of Word;
    
      TIPv4 = packed record
        case Integer of
          0: (D, C, B, A: Byte);
          1: (Groups: TIPv4ByteArray);
          2: (Value: Cardinal);
      end;
    
      TIPv6 = packed record
        case Integer of
          0: (H, G, F, E, D, C, B, A: Word);
          1: (Groups: TIPv6WordArray);
      end;
    
    Run Code Online (Sandbox Code Playgroud)
  • 问题5:将IP地址字符串转换为这些记录或数组类型:

    function StrToIPv4(const S: String): TIPv4;
    var
      SIP: String;
      Start: Integer;
      I: T4;
      Index: Integer;
      Count: Integer;
      SGroup: String;
      G: Integer;
    begin
      SIP := S + '.';
      Start := 1;
      for I := High(T4) downto Low(T4) do
      begin
        Index := PosEx('.', SIP, Start);
        if Index = 0 then
          IPv4ErrorFmt(SInvalidIPv4Value, S);
        Count := Index - Start + 1;
        SGroup := Copy(SIP, Start, Count - 1);
        if TryStrToInt(SGroup, G) and (G >= Low(Word)) and (G <= High(Word)) then
            Result.Groups[I] := G
          else
            Result.Groups[I] := 0;
        Inc(Start, Count);
      end;
    end;
    
    function StrToIPv6(const S: String): TIPv6;
    { Valid examples for S:
      2001:0db8:85a3:0000:0000:8a2e:0370:7334
      2001:db8:85a3:0:0:8a2e:370:7334
      2001:db8:85a3::8a2e:370:7334
      ::8a2e:370:7334
      2001:db8:85a3::
      ::1
      ::
      ::ffff:c000:280
      ::ffff:192.0.2.128 }
    var
      ZeroPos: Integer;
      DotPos: Integer;
      SIP: String;
      Start: Integer;
      Index: Integer;
      Count: Integer;
      SGroup: String;
      G: Integer;
    
      procedure NormalNotation;
      var
        I: T8;
      begin
        SIP := S + ':';
        Start := 1;
        for I := High(T8) downto Low(T8) do
        begin
          Index := PosEx(':', SIP, Start);
          if Index = 0 then
            IPv6ErrorFmt(SInvalidIPv6Value, S);
          Count := Index - Start + 1;
          SGroup := '$' + Copy(SIP, Start, Count - 1);
          if not TryStrToInt(SGroup, G) or (G > High(Word)) or (G < 0) then
            IPv6ErrorFmt(SInvalidIPv6Value, S);
          Result.Groups[I] := G;
          Inc(Start, Count);
        end;
      end;
    
      procedure CompressedNotation;
      var
        I: T8;
        A: array of Word;
      begin
        SIP := S + ':';
        Start := 1;
        I := High(T8);
        while Start < ZeroPos do
        begin
          Index := PosEx(':', SIP, Start);
          if Index = 0 then
            IPv6ErrorFmt(SInvalidIPv6Value, S);
          Count := Index - Start + 1;
          SGroup := '$' + Copy(SIP, Start, Count - 1);
          if not TryStrToInt(SGroup, G) or (G > High(Word)) or (G < 0) then
            IPv6ErrorFmt(SInvalidIPv6Value, S);
          Result.Groups[I] := G;
          Inc(Start, Count);
          Dec(I);
        end;
        FillChar(Result.H, (I + 1) * SizeOf(Word), 0);
        if ZeroPos < (Length(S) - 1) then
        begin
          SetLength(A, I + 1);
          Start := ZeroPos + 2;
          repeat
            Index := PosEx(':', SIP, Start);
            if Index > 0 then
            begin
              Count := Index - Start + 1;
              SGroup := '$' + Copy(SIP, Start, Count - 1);
              if not TryStrToInt(SGroup, G) or (G > High(Word)) or (G < 0) then
                IPv6ErrorFmt(SInvalidIPv6Value, S);
              A[I] := G;
              Inc(Start, Count);
              Dec(I);
            end;
          until Index = 0;
          Inc(I);
          Count := Length(A) - I;
          Move(A[I], Result.H, Count * SizeOf(Word));
        end;
      end;
    
      procedure DottedQuadNotation;
      var
        I: T4;
      begin
        if UpperCase(Copy(S, ZeroPos + 2, 4)) <> 'FFFF' then
          IPv6ErrorFmt(SInvalidIPv6Value, S);
        FillChar(Result.E, 5 * SizeOf(Word), 0);
        Result.F := $FFFF;
        SIP := S + '.';
        Start := ZeroPos + 7;
        for I := Low(T4) to High(T4) do
        begin
          Index := PosEx('.', SIP, Start);
          if Index = 0 then
            IPv6ErrorFmt(SInvalidIPv6Value, S);
          Count := Index - Start + 1;
          SGroup := Copy(SIP, Start, Count - 1);
          if not TryStrToInt(SGroup, G) or (G > High(Byte)) or (G < 0) then
            IPv6ErrorFmt(SInvalidIPv6Value, S);
          case I of
            0: Result.G := G shl 8;
            1: Inc(Result.G, G);
            2: Result.H := G shl 8;
            3: Inc(Result.H, G);
          end;
          Inc(Start, Count);
        end;
      end;
    
    begin
      ZeroPos := Pos('::', S);
      if ZeroPos = 0 then
        NormalNotation
      else
      begin
        DotPos := Pos('.', S);
        if DotPos = 0 then
          CompressedNotation
        else
          DottedQuadNotation;
      end;
    end;
    
    Run Code Online (Sandbox Code Playgroud)

对于Q1到Q3,您必须自己派生一些例程,但这不应该是任何问题.

1)对于那些感兴趣的人,它是这个滑块控件,这个主题用作本单元的启动.