这个思路是需要连接某个服务器,由服务器返回当前连接的IP,从而获得当前网络的出口公网IP;
可提供查询的网址如下
- https://ipinfo.io/ip
- https://ifconfig.io/ip
- https://ifconfig.me/ip
- https://ipecho.net/plain
- http://icanhazip.com
- http://members.3322.org/dyndns/getip
- http://whatismyip.akamai.com
返回的数据主要有几类:
- 返回IP地址;这种直接就可以使用
- 返回JSON中带有IP地址; 需要进一步解析;
- 返回一个字符串; 需要进一步解析;
Delphi实现
unit uGetWLanIP;
interface
uses
SysUtils, Classes, qjson, inifiles, uWinHttp, yxdworker;
//同步调用获取公网IP(外网IP)
function GetWLanIP:string;
//异步调用获取公网IP(外网IP)
procedure DoGetWLanIP(AJob:PJob);
var
GPublicIP : string; //外网IP/公网IP XQ220812001
implementation
uses
uLogUtils, PerlRegEx;
procedure DoGetWLanIP(AJob:PJob);
begin
GPublicIP := GetWLanIP;
end;
function GetWLanIP:string;
var
_file:Tinifile;
_iCount, I:integer;
_sValue, _sUrl, _sType, _sFieldName:string;
_sIP:string;
_lStrList:TstringList;
function CheckIP(AIP:string):Boolean;
var
_rReg : TPerlRegEx;
begin
_rReg:= TPerlRegEx.Create; //创建实例
try
//设置源字符串
_rReg.Subject:= AIP;
//设置正规表达式格式
_rReg.RegEx:= '^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$';
//执行查找
Result := _rReg.Match;
finally
//释放内存
FreeAndNil(_rReg);
end;
end;
function FromUrlGetIP(AUrl:string; AType:string; AJsonName:string=''):string;
var
_WinHttp: TWinHttp;
_Qjson:TQjson;
_sRes, _sStr:string;
begin
Result := '';
if AUrl = '' then Exit;
_WinHttp := TWinHttp.Create(nil);
_Qjson := TQJson.Create;
try
try
_WinHttp.ClearRequestHeaders;
_WinHttp.Request.ContentType := 'application/json';
_WinHttp.Request.Accept := '*/*';
_WinHttp.Request.CharSet := 'utf-8';
_WinHttp.Request.UserAgent := 'Mozilla/4.0 (compatible; Win32; WinHttp.WinHttpRequest.5)';
_WinHttp.Request.AcceptLanguage := 'zh-cn';
_WinHttp.RequestTime := 3000;
GSysLog.AddLog(Format('[获取公网IP] Request - %s', [AUrl]), ltError);
_sRes := _WinHttp.Get(AUrl);
if Length(_sRes) > 0 then
begin
GSysLog.AddLog(Format('[获取公网IP] Response - %s', [_sRes]), ltError);
if AType = 'IP' then
_sStr := Trim(_sRes)
else if AType = 'JSON' then
begin
if not _Qjson.TryParse(_sRes) then Exit;
if AJsonName = '' then Exit;
_sStr := _Qjson.ValueByName(AJsonName,'');
end
else
_sStr := '';
//检查IP是否合法
if CheckIP(_sStr) then
Result := _sStr;
end
else
begin
GSysLog.AddLog(Format('[获取公网IP] TWinHttp Err - %s', [_WinHttp.LastErrMsg]), ltError);
end;
except
on E:Exception do
begin
GSysLog.AddLog(Format('[获取公网IP] TWinHttp Err - %s', [E.Message]), ltError);
end;
end;
finally
FreeAndNil(_WinHttp);
FreeAndNil(_Qjson);
end;
end;
begin
Result := '';
_sIP := '';
//1. 读取配置文件 GetWLanIP.dat
_file := Tinifile.Create(ExtractFilePath(paramstr(0))+'GetWLanIP.dat');
_lStrList := TstringList.Create;
//1.1 读取只返回IP的
_iCount := _file.ReadInteger('URL', 'count', 0);
for I := 1 to _iCount do
begin
_sValue := trim(_file.ReadString('URL', inttostr(I), ''));
if _sValue = '' then Continue;
//分割
_lStrList.Delimiter := ',';
_lStrList.DelimitedText := _sValue;
if _lStrList.Count <> 3 then Continue;
_sUrl := _lStrList.Strings[0];
_sType := _lStrList.Strings[1];
_sFieldName := _lStrList.Strings[2];
//2. 调用WinHttp连接,获取数据
_sIP := FromUrlGetIP(_sUrl, _sType, _sFieldName);
if _sIP <> '' then Break;
end;
//未能正常获取到IP,则直接使用127.0.0.1填充
if _sIP = '' then
Result := '127.0.0.1'
else
Result := _sIP;
end;
initialization
GPublicIP := '';
end.
Pascal