我似乎无法获得或找到有关查找路由器公共IP的信息?这是因为无法通过这种方式完成,而必须从网站上获取吗?
Answers:
使用C#,使用webclient简短。
public static void Main(string[] args)
{
string externalip = new WebClient().DownloadString("http://icanhazip.com");
Console.WriteLine(externalip);
}
命令行(适用于Linux和Windows)
wget -qO- http://bot.whatismyipaddress.com
要么
curl http://ipinfo.io/ip
Trim()
的结果http://ipinfo.io/ip
。有一个尾随的空间。
static void Main(string[] args)
{
HTTPGet req = new HTTPGet();
req.Request("http://checkip.dyndns.org");
string[] a = req.ResponseBody.Split(':');
string a2 = a[1].Substring(1);
string[] a3=a2.Split('<');
string a4 = a3[0];
Console.WriteLine(a4);
Console.ReadLine();
}
使用Check IP DNS做这个小技巧
使用HTTPGet
我在Goldb-Httpget C#上找到的类
使用.Net WebRequest:
public static string GetPublicIP()
{
string url = "http://checkip.dyndns.org";
System.Net.WebRequest req = System.Net.WebRequest.Create(url);
System.Net.WebResponse resp = req.GetResponse();
System.IO.StreamReader sr = new System.IO.StreamReader(resp.GetResponseStream());
string response = sr.ReadToEnd().Trim();
string[] a = response.Split(':');
string a2 = a[1].Substring(1);
string[] a3 = a2.Split('<');
string a4 = a3[0];
return a4;
}
使用优质的类似服务
private string GetPublicIpAddress()
{
var request = (HttpWebRequest)WebRequest.Create("http://ifconfig.me");
request.UserAgent = "curl"; // this will tell the server to return the information as if the request was made by the linux "curl" command
string publicIPAddress;
request.Method = "GET";
using (WebResponse response = request.GetResponse())
{
using (var reader = new StreamReader(response.GetResponseStream()))
{
publicIPAddress = reader.ReadToEnd();
}
}
return publicIPAddress.Replace("\n", "");
}
通过@ suneel ranga扩展此答案:
static System.Net.IPAddress GetPublicIp(string serviceUrl = "https://ipinfo.io/ip")
{
return System.Net.IPAddress.Parse(new System.Net.WebClient().DownloadString(serviceUrl));
}
您将在其中使用服务的地方System.Net.WebClient
仅将IP地址显示为字符串并使用该System.Net.IPAddress
对象。以下是一些此类服务*:
https
在前面添加。我不知道为什么这里的大多数人认为通过外部ip请求正常http
。顺便说一下checkip.amazonaws.com
现在支持ssl。
从理论上讲,您的路由器应该能够告诉您网络的公共IP地址,但是这样做的方法必然是不一致的/非直截了当的,即使对于某些路由器设备而言也是可能的。
最简单但仍然非常可靠的方法是将请求发送到网页,该请求返回Web服务器看到的IP地址。Dyndns.org为此提供了良好的服务:
返回的是一个非常简单/简短的HTML文档,其中包含文本Current IP Address: 157.221.82.39
(伪IP),从HTTP响应中提取该文本很简单。
我发现http://checkip.dyndns.org/给了我必须处理的html标签,而https://icanhazip.com/却给了我一个简单的字符串。不幸的是https://icanhazip.com/给了我ip6地址,我需要ip4。幸运的是,您可以从以下两个子域中进行选择:ipv4.icanhazip.com和ipv6.icanhazip.com。
string externalip = new WebClient().DownloadString("https://ipv4.icanhazip.com/");
Console.WriteLine(externalip);
Console.WriteLine(externalip.TrimEnd());
用几行代码,您可以为此编写自己的Http Server。
HttpListener listener = new HttpListener();
listener.Prefixes.Add("http://+/PublicIP/");
listener.Start();
while (true)
{
HttpListenerContext context = listener.GetContext();
string clientIP = context.Request.RemoteEndPoint.Address.ToString();
using (Stream response = context.Response.OutputStream)
using (StreamWriter writer = new StreamWriter(response))
writer.Write(clientIP);
context.Response.Close();
}
然后,只要您需要知道公共IP,就可以执行此操作。
WebClient client = new WebClient();
string ip = client.DownloadString("http://serverIp/PublicIP");
无需任何连接即可获取外部ip的快速方法实际上,无需任何Http连接
首先,您必须在引用上添加NATUPNPLib.dll并从引用中选择它,然后从属性窗口中检查将Interop Type嵌入False
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NATUPNPLib; // Add this dll from referance and chande Embed Interop Interop to false from properties panel on visual studio
using System.Net;
namespace Client
{
class NATTRAVERSAL
{
//This is code for get external ip
private void NAT_TRAVERSAL_ACT()
{
UPnPNATClass uPnP = new UPnPNATClass();
IStaticPortMappingCollection map = uPnP.StaticPortMappingCollection;
foreach (IStaticPortMapping item in map)
{
Debug.Print(item.ExternalIPAddress); //This line will give you external ip as string
break;
}
}
}
}
基本上,我更喜欢使用一些额外的备份,以防IP之一无法访问。所以我用这种方法。
public static string GetExternalIPAddress()
{
string result = string.Empty;
try
{
using (var client = new WebClient())
{
client.Headers["User-Agent"] =
"Mozilla/4.0 (Compatible; Windows NT 5.1; MSIE 6.0) " +
"(compatible; MSIE 6.0; Windows NT 5.1; " +
".NET CLR 1.1.4322; .NET CLR 2.0.50727)";
try
{
byte[] arr = client.DownloadData("http://checkip.amazonaws.com/");
string response = System.Text.Encoding.UTF8.GetString(arr);
result = response.Trim();
}
catch (WebException)
{
}
}
}
catch
{
}
if (string.IsNullOrEmpty(result))
{
try
{
result = new WebClient().DownloadString("https://ipinfo.io/ip").Replace("\n", "");
}
catch
{
}
}
if (string.IsNullOrEmpty(result))
{
try
{
result = new WebClient().DownloadString("https://api.ipify.org").Replace("\n", "");
}
catch
{
}
}
if (string.IsNullOrEmpty(result))
{
try
{
result = new WebClient().DownloadString("https://icanhazip.com").Replace("\n", "");
}
catch
{
}
}
if (string.IsNullOrEmpty(result))
{
try
{
result = new WebClient().DownloadString("https://wtfismyip.com/text").Replace("\n", "");
}
catch
{
}
}
if (string.IsNullOrEmpty(result))
{
try
{
result = new WebClient().DownloadString("http://bot.whatismyipaddress.com/").Replace("\n", "");
}
catch
{
}
}
if (string.IsNullOrEmpty(result))
{
try
{
string url = "http://checkip.dyndns.org";
System.Net.WebRequest req = System.Net.WebRequest.Create(url);
System.Net.WebResponse resp = req.GetResponse();
System.IO.StreamReader sr = new System.IO.StreamReader(resp.GetResponseStream());
string response = sr.ReadToEnd().Trim();
string[] a = response.Split(':');
string a2 = a[1].Substring(1);
string[] a3 = a2.Split('<');
result = a3[0];
}
catch (Exception)
{
}
}
return result;
}
为了更新GUI控件(WPF,.NET 4.5),例如某些Label,我使用此代码
void GetPublicIPAddress()
{
Task.Factory.StartNew(() =>
{
var ipAddress = SystemHelper.GetExternalIPAddress();
Action bindData = () =>
{
if (!string.IsNullOrEmpty(ipAddress))
labelMainContent.Content = "IP External: " + ipAddress;
else
labelMainContent.Content = "IP External: ";
labelMainContent.Visibility = Visibility.Visible;
};
this.Dispatcher.InvokeAsync(bindData);
});
}
希望它是有用的。
这是一个包含此代码的应用示例。
checkip.dyndns.org并非总是能正常工作。例如,对于我的机器,它显示内部的NAT后地址:
Current IP Address: 192.168.1.120
我认为它的发生是因为我在NAT后面有我的本地DNS区域,并且我的浏览器发送了校验它的本地IP地址,并将其返回。
另外,http是重量级且基于文本的基于TCP的协议,因此不太适合快速有效地定期请求外部IP地址。我建议使用基于UDP的二进制STUN,它是专门为此目的而设计的:
http://en.wikipedia.org/wiki/STUN
STUN服务器就像“ UDP镜像”。您期待着它,然后看到“我的样子”。
世界上有许多公共STUN服务器,您可以在其中请求外部IP。例如,在这里:
http://www.voip-info.org/wiki/view/STUN
您可以从Internet下载任何STUN客户端库,例如,在这里:
http://www.codeproject.com/Articles/18492/STUN-Client
并使用它。
private static string GetPublicIpAddress()
{
using (var client = new WebClient())
{
return client.DownloadString("http://ifconfig.me").Replace("\n", "");
}
}
当我调试时,我使用以下命令来构造可外部调用的URL,但是您可以仅使用前两行来获取您的公共IP:
public static string ExternalAction(this UrlHelper helper, string actionName, string controllerName = null, RouteValueDictionary routeValues = null, string protocol = null)
{
#if DEBUG
var client = new HttpClient();
var ipAddress = client.GetStringAsync("http://ipecho.net/plain").Result;
// above 2 lines should do it..
var route = UrlHelper.GenerateUrl(null, actionName, controllerName, routeValues, helper.RouteCollection, helper.RequestContext, true);
if (route == null)
{
return route;
}
if (string.IsNullOrEmpty(protocol) && string.IsNullOrEmpty(ipAddress))
{
return route;
}
var url = HttpContext.Current.Request.Url;
protocol = !string.IsNullOrWhiteSpace(protocol) ? protocol : Uri.UriSchemeHttp;
return string.Concat(protocol, Uri.SchemeDelimiter, ipAddress, route);
#else
helper.Action(action, null, null, HttpContext.Current.Request.Url.Scheme)
#endif
}
GetStringAsync()
您在此处使用时,使用HttpClient
而不是使用的Get Request对我来说要快得多WebRequest
。我可以确认这就像一个魅力。
我这样做是HttpClient
从System.Net.Http
:
public static string PublicIPAddress()
{
string uri = "http://checkip.dyndns.org/";
string ip = String.Empty;
using (var client = new HttpClient())
{
var result = client.GetAsync(uri).Result.Content.ReadAsStringAsync().Result;
ip = result.Split(':')[1].Split('<')[0];
}
return ip;
}
我找到的最佳答案
要获得最快的IP地址,可能是最快的方法。您必须使用下载器或在计算机上创建服务器。
使用此简单代码:(推荐)的缺点是,将需要3-5秒来获取您的远程IP地址,因为在初始化时,WebClient始终需要3-5秒来检查代理设置。
public static string GetIP()
{
string externalIP = "";
externalIP = new WebClient().DownloadString("http://checkip.dyndns.org/");
externalIP = (new Regex(@"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"))
.Matches(externalIP)[0].ToString();
return externalIP;
}
这是我固定的方法..(第一次仍然需要3-5秒),但之后,它将始终在0-2秒内获得您的远程IP地址,具体取决于您的连接。
public static WebClient webclient = new WebClient();
public static string GetIP()
{
string externalIP = "";
externalIP = webclient.DownloadString("http://checkip.dyndns.org/");
externalIP = (new Regex(@"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"))
.Matches(externalIP)[0].ToString();
return externalIP;
}
我已经将@Academy of Programmer的答案简化为较短的代码,并对其进行了更改,使其仅命中https://
URL:
public static string GetExternalIPAddress()
{
string result = string.Empty;
string[] checkIPUrl =
{
"https://ipinfo.io/ip",
"https://checkip.amazonaws.com/",
"https://api.ipify.org",
"https://icanhazip.com",
"https://wtfismyip.com/text"
};
using (var client = new WebClient())
{
client.Headers["User-Agent"] = "Mozilla/4.0 (Compatible; Windows NT 5.1; MSIE 6.0) " +
"(compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)";
foreach (var url in checkIPUrl)
{
try
{
result = client.DownloadString(url);
}
catch
{
}
if (!string.IsNullOrEmpty(result))
break;
}
}
return result.Replace("\n", "").Trim();
}
}
基于使用外部Web服务的答案并不完全正确,因为它们实际上并未回答所述问题:
...有关找到我的路由器公共IP的信息
说明
所有在线服务都返回外部IP地址, 但实际上并不意味着该地址已分配给用户的路由器。
可以为路由器分配ISP基础结构网络的另一个本地IP地址。实际上,这意味着该路由器无法托管Internet上可用的任何服务。这可能对大多数家庭用户的安全有好处,但对在家托管服务器的极客不利。
以下是检查路由器是否具有外部IP的方法:
根据Wikipedia的文章,IP地址范围为10.0.0.0 – 10.255.255.255
,172.16.0.0 – 172.31.255.255
并且192.168.0.0 – 192.168.255.255
用于私有网络(即本地网络)。
查看当您跟踪到某个远程主机的路由并为路由器分配了外部IP地址时会发生什么:
知道了!第一跳从31.*
现在开始。这显然意味着您的路由器和Internet之间没有任何联系。
解
Ttl = 2
TTL = 2必须不足以到达远程主机。跃点1主机将发出"Reply from <ip address>: TTL expired in transit."
并显示其IP地址。
实作
try
{
using (var ping = new Ping())
{
var pingResult = ping.Send("google.com");
if (pingResult?.Status == IPStatus.Success)
{
pingResult = ping.Send(pingResult.Address, 3000, "ping".ToAsciiBytes(), new PingOptions { Ttl = 2 });
var isRealIp = !Helpers.IsLocalIp(pingResult?.Address);
Console.WriteLine(pingResult?.Address == null
? $"Has {(isRealIp ? string.Empty : "no ")}real IP, status: {pingResult?.Status}"
: $"Has {(isRealIp ? string.Empty : "no ")}real IP, response from: {pingResult.Address}, status: {pingResult.Status}");
Console.WriteLine($"ISP assigned REAL EXTERNAL IP to your router, response from: {pingResult?.Address}, status: {pingResult?.Status}");
}
else
{
Console.WriteLine($"Your router appears to be behind ISP networks, response from: {pingResult?.Address}, status: {pingResult?.Status}");
}
}
}
catch (Exception exc)
{
Console.WriteLine("Failed to resolve external ip address by ping");
}
小助手用于检查IP是属于专用网络还是公用网络:
public static bool IsLocalIp(IPAddress ip) {
var ipParts = ip.ToString().Split(new [] { "." }, StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToArray();
return (ipParts[0] == 192 && ipParts[1] == 168)
|| (ipParts[0] == 172 && ipParts[1] >= 16 && ipParts[1] <= 31)
|| ipParts[0] == 10;
}
您可以使用Telnet以编程方式向路由器查询WAN IP。
Telnet部分
例如,可以使用此简约Telnet代码作为API将Telnet命令发送到路由器并获取路由器的响应,从而完成Telnet部分。此答案的其余部分假定您已设置为以某种方式发送Telnet命令并获取代码中的响应。
方法的局限性
我会先说,与其他方法相比,查询路由器的一个缺点是您编写的代码可能非常特定于您的路由器模型。也就是说,这是一种不依赖外部服务器的有用方法,并且您可能仍然希望从自己的软件访问路由器以用于其他目的,例如配置和控制它,使其更值得编写特定的代码。
路由器命令和响应示例
以下示例并非适用于所有路由器,但原则上说明了该方法。您将需要更改详细信息以适合您的路由器命令和响应。
例如,使路由器显示WAN IP的方法可能是以下Telnet命令:
connection list
输出可能包含一系列文本行,每个连接一个,其IP地址在偏移量39处。WAN连接行可以从该行中的“ Internet”一词中识别出来:
RESP: 3947 17.110.226. 13:443 146.200.253. 16:60642 [R..A] Internet 6 tcp 128
<------------------ 39 -------------><-- WAN IP -->
输出可能会将每个IP地址段填充为三个空格,您需要将其删除。(也就是说,在上面的示例中,您需要将“ 146.200.253。16”变成“ 146.200.253.16”。)
通过试验或查阅路由器的参考文档,可以建立用于特定路由器的命令以及如何解释路由器的响应。
获取WAN IP的代码
(假设您有sendRouterCommand
用于Telnet部分的方法-参见上文。)
使用上述示例路由器,以下代码将获取WAN IP:
private bool getWanIp(ref string wanIP)
{
string routerResponse = sendRouterCommand("connection list");
return (getWanIpFromRouterResponse(routerResponse, out wanIP));
}
private bool getWanIpFromRouterResponse(string routerResponse, out string ipResult)
{
ipResult = null;
string[] responseLines = routerResponse.Split(new char[] { '\n' });
// RESP: 3947 17.110.226. 13:443 146.200.253. 16:60642 [R..A] Internet 6 tcp 128
//<------------------ 39 -------------><--- 15 --->
const int offset = 39, length = 15;
foreach (string line in responseLines)
{
if (line.Length > (offset + length) && line.Contains("Internet"))
{
ipResult = line.Substring(39, 15).Replace(" ", "");
return true;
}
}
return false;
}
大多数答案在解决方案中都提到了http://checkip.dyndns.org。对于我们来说,效果并不理想。我们已经面对超时很多时间了。如果您的程序依赖于IP检测,那真的很麻烦。
作为解决方案,我们在一个桌面应用程序中使用以下方法:
// Returns external/public ip
protected string GetExternalIP()
{
try
{
using (MyWebClient client = new MyWebClient())
{
client.Headers["User-Agent"] =
"Mozilla/4.0 (Compatible; Windows NT 5.1; MSIE 6.0) " +
"(compatible; MSIE 6.0; Windows NT 5.1; " +
".NET CLR 1.1.4322; .NET CLR 2.0.50727)";
try
{
byte[] arr = client.DownloadData("http://checkip.amazonaws.com/");
string response = System.Text.Encoding.UTF8.GetString(arr);
return response.Trim();
}
catch (WebException ex)
{
// Reproduce timeout: http://checkip.amazonaws.com:81/
// trying with another site
try
{
byte[] arr = client.DownloadData("http://icanhazip.com/");
string response = System.Text.Encoding.UTF8.GetString(arr);
return response.Trim();
}
catch (WebException exc)
{ return "Undefined"; }
}
}
}
catch (Exception ex)
{
// TODO: Log trace
return "Undefined";
}
}
很好的一点是,两个站点都以纯格式返回IP。因此避免了字符串操作。
要检查incatch
子句的逻辑,可以通过击中不可用的端口来重现超时。例如:http : //checkip.amazonaws.com : 81/
我发现大多数其他答案都缺乏,因为他们认为任何返回的字符串都必须是IP,但并没有真正对其进行检查。这是我目前正在使用的解决方案。它只会返回有效的IP或如果找不到则返回null。
public class WhatsMyIp
{
public static IPAddress PublicIp { get; private set; }
static WhatsMyIp()
{
PublicIp = GetMyIp();
}
public static IPAddress GetMyIp()
{
List<string> services = new List<string>()
{
"https://ipv4.icanhazip.com",
"https://api.ipify.org",
"https://ipinfo.io/ip",
"https://checkip.amazonaws.com",
"https://wtfismyip.com/text",
"http://icanhazip.com"
};
using (var webclient = new WebClient())
foreach (var service in services)
{
try { return IPAddress.Parse(webclient.DownloadString(service)); } catch { }
}
return null;
}
}
public string GetClientIp() {
var ipAddress = string.Empty;
if (System.Web.HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"] != null) {
ipAddress = System.Web.HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"].ToString();
} else if (System.Web.HttpContext.Current.Request.ServerVariables["HTTP_CLIENT_IP"] != null &&
System.Web.HttpContext.Current.Request.ServerVariables["HTTP_CLIENT_IP"].Length != 0) {
ipAddress = System.Web.HttpContext.Current.Request.ServerVariables["HTTP_CLIENT_IP"];
} else if (System.Web.HttpContext.Current.Request.UserHostAddress.Length != 0) {
ipAddress = System.Web.HttpContext.Current.Request.UserHostName;
}
return ipAddress;
}
完美的作品
using System.Net;
private string GetWorldIP()
{
String url = "http://bot.whatismyipaddress.com/";
String result = null;
try
{
WebClient client = new WebClient();
result = client.DownloadString(url);
return result;
}
catch (Exception ex) { return "127.0.0.1"; }
}
使用回送作为回退,只是为了避免发生致命故障。
我和Jesper几乎一样,只是我重新使用了Webclient并正确处理了它。另外,我通过删除最后的\ n清理了一些响应。
private static IPAddress GetExternalIp () {
using (WebClient client = new WebClient()) {
List<String> hosts = new List<String>();
hosts.Add("https://icanhazip.com");
hosts.Add("https://api.ipify.org");
hosts.Add("https://ipinfo.io/ip");
hosts.Add("https://wtfismyip.com/text");
hosts.Add("https://checkip.amazonaws.com/");
hosts.Add("https://bot.whatismyipaddress.com/");
hosts.Add("https://ipecho.net/plain");
foreach (String host in hosts) {
try {
String ipAdressString = client.DownloadString(host);
ipAdressString = ipAdressString.Replace("\n", "");
return IPAddress.Parse(ipAdressString);
} catch {
}
}
}
return null;
}
或这样,我认为我需要的东西效果很好。是从这里来的。
public IPAddress GetExternalIP()
{
WebClient lol = new WebClient();
string str = lol.DownloadString("http://www.ip-adress.com/");
string pattern = "<h2>My IP address is: (.+)</h2>"
MatchCollection matches1 = Regex.Matches(str, pattern);
string ip = matches1(0).ToString;
ip = ip.Remove(0, 21);
ip = ip.Replace("
", "");
ip = ip.Replace(" ", "");
return IPAddress.Parse(ip);
}