我想检查IP地址是否在最小和最大IP地址的范围内。我怎样才能在德尔福做到这一点?
例如,我想做这样的事情:
if CheckIp("127.0.0.15","127.0.0.1","127.0.0.255") then ShowMessage('ok');
127.0.0.1是范围的起始值,127.0.0.255是范围的结束值,127.0.0.15是将要检查的IP地址。
我之前在这里问了一个稍微类似的问题,关于IP地址的一般字符串例程。基于NGLN的回答,我实现了一组比较函数和一个演示应用程序。功能IPRange
检测它是v4还是v6,并进行相应的比较。
乌曼帕斯酒店
unit uMain;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls,
IPTypes;
type
TfrmCheckIPRange = class(TForm)
txtFrom: TEdit;
txtTo: TEdit;
txtIP: TEdit;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
txtResult: TEdit;
Label4: TLabel;
procedure DoCheck(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
frmCheckIPRange: TfrmCheckIPRange;
implementation
{$R *.dfm}
function IntRange(const Val, Min, Max: Integer): Boolean;
begin
Result:= (Val >= Min) and (Val <= Max);
end;
function IPRangeV4(const IP, IPFrom, IPTo: TIPv4): Boolean;
begin
Result:= IntRange(IP.D, IPFrom.D, IPTo.D);
if Result then
Result:= IntRange(IP.C, IPFrom.C, IPTo.C);
if Result then
Result:= IntRange(IP.B, IPFrom.B, IPTo.B);
if Result then
Result:= IntRange(IP.A, IPFrom.A, IPTo.A);
end;
function IPRangeV6(const IP, IPFrom, IPTo: TIPv6): Boolean;
begin
Result:= IntRange(IP.H, IPFrom.H, IPTo.H);
if Result then
Result:= IntRange(IP.G, IPFrom.G, IPTo.G);
if Result then
Result:= IntRange(IP.F, IPFrom.F, IPTo.F);
if Result then
Result:= IntRange(IP.E, IPFrom.E, IPTo.E);
if Result then
Result:= IntRange(IP.D, IPFrom.D, IPTo.D);
if Result then
Result:= IntRange(IP.C, IPFrom.C, IPTo.C);
if Result then
Result:= IntRange(IP.B, IPFrom.B, IPTo.B);
if Result then
Result:= IntRange(IP.A, IPFrom.A, IPTo.A);
end;
function IPRange(const IP, IPFrom, IPTo: String): Boolean;
var
IP4, FR4, TO4: TIPv4;
IP6, FR6, TO6: TIPv6;
function IsV4(const S: String): Boolean;
begin
Result:= Pos('.', S) > 1;
end;
function IsV6(const S: String): Boolean;
begin
Result:= Pos(':', S) > 0;
end;
begin
Result:= False;
if (IsV6(IP)) and (IsV6(IPFrom)) and (IsV6(IPTo)) then begin
IP6:= StrToIPv6(IP);
FR6:= StrToIPv6(IPFrom);
TO6:= StrToIPv6(IPTo);
Result:= IPRangeV6(IP6, FR6, TO6);
end else
if (IsV4(IP)) and (IsV4(IPFrom)) and (IsV4(IPTo)) then begin
IP4:= StrToIPv4(IP);
FR4:= StrToIPv4(IPFrom);
TO4:= StrToIPv4(IPTo);
Result:= IPRangeV4(IP4, FR4, TO4);
end else begin
raise Exception.Create('Invalid IP Address Input');
end;
end;
{ TfrmCheckIPRange }
procedure TfrmCheckIPRange.FormCreate(Sender: TObject);
begin
DoCheck(nil);
end;
procedure TfrmCheckIPRange.DoCheck(Sender: TObject);
begin
try
if IPRange(txtIP.Text, txtFrom.Text, txtTo.Text) then begin
txtResult.Text:= 'IP is in range';
txtResult.Color:= clGreen;
end else begin
txtResult.Text:= 'IP is NOT in range';
txtResult.Color:= clRed;
end;
except
on e: exception do begin
txtResult.Text:= e.Message;
txtResult.Color:= clYellow;
end;
end;
end;
end.
uMain.dfm
object frmCheckIPRange: TfrmCheckIPRange
Left = 350
Top = 113
BorderIcons = [biSystemMenu]
BorderStyle = bsSingle
Caption = 'Check IP Range'
ClientHeight = 124
ClientWidth = 296
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
Position = poScreenCenter
OnCreate = FormCreate
DesignSize = (
296
124)
PixelsPerInch = 96
TextHeight = 13
object Label1: TLabel
Left = 11
Top = 11
Width = 71
Height = 13
Alignment = taRightJustify
Caption = 'IP To Compare'
end
object Label2: TLabel
Left = 11
Top = 38
Width = 71
Height = 13
Alignment = taRightJustify
Caption = 'IP Range From'
end
object Label3: TLabel
Left = 23
Top = 65
Width = 59
Height = 13
Alignment = taRightJustify
Caption = 'IP Range To'
end
object Label4: TLabel
Left = 52
Top = 92
Width = 30
Height = 13
Alignment = taRightJustify
Caption = 'Result'
end
object txtFrom: TEdit
Left = 88
Top = 35
Width = 196
Height = 21
Anchors = [akLeft, akTop, akRight]
TabOrder = 1
Text = '192.168.3.100'
OnChange = DoCheck
ExplicitWidth = 158
end
object txtTo: TEdit
Left = 88
Top = 62
Width = 196
Height = 21
Anchors = [akLeft, akTop, akRight]
TabOrder = 2
Text = '192.168.3.200'
OnChange = DoCheck
ExplicitWidth = 158
end
object txtIP: TEdit
Left = 88
Top = 8
Width = 196
Height = 21
Anchors = [akLeft, akTop, akRight]
TabOrder = 0
Text = '192.168.3.105'
OnChange = DoCheck
ExplicitWidth = 158
end
object txtResult: TEdit
Left = 88
Top = 89
Width = 196
Height = 21
Anchors = [akLeft, akTop, akRight]
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = [fsBold]
ParentFont = False
ReadOnly = True
TabOrder = 3
OnChange = DoCheck
ExplicitWidth = 158
end
end
我已经测试了IPv4,但还没有测试IPv6,尽管它应该可以工作。我对IPv6还不够熟悉,甚至不知道不同的测试场景。
您可能还需要添加一些逻辑来检查IP是否在同一子网内,因为您可能不希望包含不同的子网。这就像确保前3个数字(v4)完全相同一样简单。如果子网之间存在任何差异,您可能希望提出一个例外,但这取决于您需要如何实现它。
编辑
我修复了确定v4与v6的逻辑,因为IPv6地址中也可能包含,我必须将检查顺序从v4-v6切换到v6-v4。
我将假设您的地址是以主机字节顺序存储在32位整数中的IPv4地址。我还假设你需要一个词典排序,这样:
a.b.c.d < p.q.r.s
通过首先比较a
和p
进行比较,如果相等,则比较b
和q
,依此类推。
在这种情况下,自然无符号整数排序(使用
如果地址是按网络字节顺序排列的,那么在比较之前需要转换为主机字节顺序。
在你的问题中,地址是字符串。因此,您需要将它们转换为具有
inet_addr
的网络字节顺序32位无符号整数,然后将它们转换为具有ntohl
的主机字节顺序。然后你可以比较。
对于IPv4地址,您可以简单地将其转换为整数形式,然后对其执行标准顺序比较。
IPv6地址太大,无法转换为整数(除非您使用第三方BigInt库),因此您必须将它们转换为二进制形式,并逐字节进行比较。
我有一个IP地址,我得到了另外两个IP地址,它们一起创建了一个IP范围。我想检查第一个IP地址是否在这个范围内。我怎么能在不使用循环的情况下在Python中找到它?
我有一个IP地址,另外两个IP地址一起创建了一个IP范围。我想检查第一个IP地址是否在此范围内。如何在PHP中找到它?
问题内容: 我有一个IP地址,并给了我另外两个IP地址,它们一起创建了IP范围。我想检查第一个IP地址是否在此范围内。如何在PHP中找到答案? 问题答案: 有了它可以轻松地将地址转换为数字。之后,您只需要检查数字是否在范围内:
问题内容: 我希望能够根据其他两个IP范围内的IP返回true / false。 例如: 结果应为true。 其他例子: 问题答案: 检查范围的最简单方法可能是将IP地址转换为32位整数,然后比较这些整数。 而不是,您可能想要查看具有InetAddresses帮助器类的Guava库,该类避免了DNS查找的可能性。
问题内容: 如何从起始IP地址和结束IP地址生成一系列IP地址? 网络“ 192.168.0.0/24”的示例: 我希望有: PS:网络,起始和结束IP可以是动态的,上面仅是一个示例。 谢谢… 问题答案: 认识到IPv4地址的4个组成部分实际上都是00到FF之间的十六进制数字。 如果将起始IP地址和结束IP地址更改为32位无符号整数,则可以从最低的一个循环到最高的一个,然后将循环通过的每个值转换回
我想展示一个IP的两个第一范围。例如,我127.0.0.1。我想得到127.0并使用这个例子: show show 我怎么能那样做? 我尝试了,但它显示了整个IP地址。