📄 unitqueryip.pas
字号:
unit UnitQueryIP;
interface
uses Forms, Windows, Classes, SysUtils, WinSock;
const
DEFAULT_IPFILENAME = 'IPWry.dat';
INDEX_SIZE = 7;
type
TQueryIP = class
private
IpDataFile: TFileStream;
IndexStart: Cardinal;
IndexEnd: Cardinal;
function ReadByte(Offset: Cardinal; Num: integer): Cardinal;
function ReadStr(Offset: Cardinal): String;
public
constructor Create(IpDataBase: string);
function QueryIP(aIP: Cardinal): string; overload;
function QueryIP(aIP: String): string; overload;
end;
function IPQuery: TQueryIP;
implementation
var IPCache: TStringList;
_IPQuery: TQueryIP = nil;
function IPQuery: TQueryIP;
begin
if not Assigned(_IPQuery) then
_IPQuery := TQueryIP.Create(ExtractFilePath(ParamStr(0)) + 'IPWry.dat');
Result := _IPQuery;
end;
constructor TQueryIP.Create(IpDataBase: string);
begin
if not FileExists(IpDataBase) then
begin
IpDataBase := ExtractFilePath(Application.ExeName)+IpDataBase;
if not FileExists(IpDataBase) then
IpDataBase := ExtractFilePath(Application.ExeName)+DEFAULT_IPFILENAME;
end;
try
IpDataFile := TFileStream.Create(IpDataBase, fmOpenRead or fmShareDenyWrite);
except
IpDataFile := nil;
end;
if IpDataFile<>nil then
begin
IndexStart := ReadByte(0, 4);
IndexEnd := ReadByte(4, 4);
end else
begin
IndexStart := 0;
IndexEnd := 0;
end;
end;
function TQueryIP.QueryIP(aIP: Cardinal): string;
var StartPos, EndPos, Middle, ResultRecordPos: Cardinal;
IndexIP: Cardinal;
EndIP, RedirectMode: Cardinal;
CountryPos, AreaPos: Cardinal;
Country, Area: string;
addr: in_addr;
begin
Result := '非法IP格式';
if integer(aIP)=-1 then
exit;
if IpDataFile=nil then
exit;
StartPos := IndexStart;
EndPos := IndexEnd;
ResultRecordPos := 0;
while ResultRecordPos=0 do
begin
Middle := StartPos + (((EndPos - StartPos) div INDEX_SIZE) div 2) * INDEX_SIZE;
if (Middle=StartPos) then
begin
IndexIP := ReadByte(EndPos, 4);
if IndexIP<=aIP then
ResultRecordPos := ReadByte(EndPos+4, 3)
else
ResultRecordPos := ReadByte(StartPos+4, 3);
break;
end;
IndexIP := ReadByte(Middle, 4);
if IndexIP = aIP then
begin
ResultRecordPos := ReadByte(Middle+4, 3);
break;
end else
begin
if IndexIP>aIP then
EndPos := Middle
else
StartPos := Middle;
end;
end;
if ResultRecordPos=0 then
exit;
EndIP := ReadByte(ResultRecordPos, 4);
if aIP>EndIP then
exit;
RedirectMode := ReadByte(ResultRecordPos+4, 1);
if (RedirectMode<>1) and (RedirectMode<>2) then
begin
Country := ReadStr(ResultRecordPos+4);
Area := ReadStr(IpDataFile.Position);
end else
if RedirectMode=1 then
begin
CountryPos := ReadByte(ResultRecordPos+5, 3);
RedirectMode := ReadByte(CountryPos, 1); // 国家重定向模式
if (RedirectMode<>1) and (RedirectMode<>2) then
begin
Country := ReadStr(CountryPos);
AreaPos := IpDataFile.Position;
RedirectMode := ReadByte(AreaPos, 1); // 地区重定向模式
if (RedirectMode<>1) and (RedirectMode<>2) then
begin
Area := ReadStr(AreaPos);
end else
begin
AreaPos := ReadByte(AreaPos+1, 3);; // 地区信息字符串地址
Area := ReadStr(AreaPos);
end;
end else
begin
AreaPos := CountryPos+4;
CountryPos := ReadByte(CountryPos+1, 3); // 国家信息字符串地址
Country := ReadStr(CountryPos);
RedirectMode := ReadByte(AreaPos, 1); // 地区重定向模式
if (RedirectMode<>1) and (RedirectMode<>2) then
begin
Area := ReadStr(AreaPos);
end else
begin
AreaPos := ReadByte(AreaPos+1, 3);; // 地区信息字符串地址
Area := ReadStr(AreaPos);
end;
end;
end else
if RedirectMode=2 then
begin
CountryPos := ReadByte(IpDataFile.Position, 3); // 国家信息字符串地址
ResultRecordPos := IpDataFile.Position;
RedirectMode := ReadByte(ResultRecordPos, 1); // 地区信息重定向模式
Country := ReadStr(CountryPos);
if (RedirectMode<>1) and (RedirectMode<>2) then
begin
AreaPos := ResultRecordPos; // 地区信息字符串地址
Area := ReadStr(AreaPos);
end else
begin
AreaPos := ReadByte(ResultRecordPos+1, 3);; // 地区信息字符串地址
Area := ReadStr(AreaPos);
end;
end;
if Country='IANA' then
Result := '未知IP'
else
if Country='局域网' then
begin
addr.S_addr := ntohl(aIP);
Result := '同局域网内 IP:'+inet_ntoa(addr);
end
else
begin
if Area = '' then
Result := Country
else
Result := Country + ' ' + Area;
end;
end;
// 从指定偏移处读出Num字节的数据
function TQueryIP.QueryIP(aIP: String): string;
begin
Result := QueryIP(htonl(inet_addr(PChar(aIP))));
end;
function TQueryIP.ReadByte(Offset: Cardinal; Num: integer): Cardinal;
var Buf: Cardinal;
I: integer;
begin
Result := 0;
if IpDataFile=nil then
exit;
IpDataFile.Position := Offset;
for I := 0 to Num - 1 do
begin
IpDataFile.ReadBuffer(Buf, 1);
Result := (Buf shl (I*8)) or Result;
end;
end;
// 从指定偏移处读出以0为结尾的字符串
function TQueryIP.ReadStr(Offset: Cardinal): String;
var Buf: char;
begin
Result := '';
if Offset<20 then
exit;
if IpDataFile=nil then
exit;
IpDataFile.Position := Offset;
repeat
if IpDataFile.Read(Buf, 1)<=0 then
break;
if Buf=char(0) then
break;
Result := Result + Buf;
until False;
end;
initialization
_IPQuery := TQueryIP.Create(ExtractFilePath(ParamStr(0)) + 'IPWry.dat');
finalization
_IPQuery.Free;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -