获取公共/外部IP地址?

时间:2010-07-15 08:18:53

标签: c# networking ip-address

我似乎无法获取或找到有关查找路由器公共IP的信息?这是因为它不能以这种方式完成并且必须从网站上获取它吗?

27 个答案:

答案 0 :(得分:81)

使用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

OR

curl http://ipinfo.io/ip

答案 1 :(得分:69)

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

执行此小操作

使用Goldb-Httpget C#

上的HTTPGet课程

答案 2 :(得分:35)

使用.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;
    }

答案 3 :(得分:28)

string pubIp =  new System.Net.WebClient().DownloadString("https://api.ipify.org");

答案 4 :(得分:18)

类似服务

private string GetPublicIpAddress()
        {
            var request = (HttpWebRequest)WebRequest.Create("http://ifconfig.me");

            request.UserAgent = "curl"; // this simulate curl linux 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", "");
        }

答案 5 :(得分:13)

理论上,您的路由器应该能够告诉您网络的公共IP地址,但是这样做的方式必然是不一致/非直接的,即使对某些路由器设备也是如此。

最简单且非常可靠的方法是向网页发送请求,该网页会在Web服务器看到它时返回您的IP地址。 Dyndns.org为此提供了良好的服务:

  

http://checkip.dyndns.org/

返回的是一个非常简单/简短的HTML文档,其中包含文本Current IP Address: 157.221.82.39(假IP),从HTTP响应中提取这些文档非常简单。

答案 6 :(得分:9)

通过@ answer扩展此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对象。以下是一些此类服务*:

*此问题及answers from superuser site中提到了一些服务。

答案 7 :(得分:6)

使用几行代码,您可以为此编写自己的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");

答案 8 :(得分:6)

快速获取没有任何连接的外部IP的方法Actualy不需要任何Http连接

首先必须在Referance上添加NATUPNPLib.dll 并从referances中选择它并从属性窗口中检查Embed 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;
            }
        }
    }
}

答案 9 :(得分:5)

我发现http://checkip.dyndns.org/给了我必须处理的html标签,但是https://icanhazip.com/只是给了我一个简单的字符串。不幸的是https://icanhazip.com/给了我ip6地址,我需要ip4。幸运的是,您可以选择2个子域名,ipv4.icanhazip.com和ipv6.icanhazip.com。

        string externalip = new WebClient().DownloadString("https://ipv4.icanhazip.com/");
        Console.WriteLine(externalip);
        Console.WriteLine(externalip.TrimEnd());

答案 10 :(得分:5)

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-server就像“UDP镜像”。你期待它,看看“我的样子”。

世界上有许多公共STUN服务器,您可以在那里请求外部IP。 例如,请看这里:

http://www.voip-info.org/wiki/view/STUN

您可以从Internet下载任何STUN-client库,例如:

http://www.codeproject.com/Articles/18492/STUN-Client

并使用它。

答案 11 :(得分:4)

基本上我更喜欢使用一些额外的备份,以防其中一个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);
            });

 }

希望它有用。

Here是包含此代码的应用示例。

答案 12 :(得分:4)

我使用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;
}

答案 13 :(得分:4)

public static string GetPublicIP()
{
    return new System.Net.WebClient().DownloadString("https://ipinfo.io/ip").Replace("\n","");
}

答案 14 :(得分:3)

基于使用外部Web服务的答案并不完全正确,因为它们实际上并未回答所述问题:

  

...有关查找我的路由器公共IP

的信息

说明

所有在线服务均返回外部IP地址, 但从本质上讲并不意味着该地址已分配给用户的路由器。

可以为路由器分配ISP基础结构网络的另一个本地IP地址。实际上,这意味着该路由器无法托管Internet上可用的任何服务。这可能对大多数家庭用户的安全有好处,但对在家托管服务器的极客却不利。

这里是检查路由器是否具有外部IP的方法:

trace route to web server behind ISP

根据Wikipedia文章,IP地址范围10.0.0.0 – 10.255.255.255172.16.0.0 – 172.31.255.255192.168.0.0 – 192.168.255.255用于私有(即本地网络)。

查看当您跟踪到某个远程主机且路由分配了外部IP地址的远程主机时会发生什么:

trace route to web server with external IP address

陷阱!第一跳现在从31.*开始。这显然意味着您的路由器和Internet之间没有任何联系。


解决方案

  1. 使用Ttl = 2将Ping到某个地址
  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;
}

答案 15 :(得分:3)

当我调试时,我使用以下来构建外部可调用的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
}

答案 16 :(得分:2)

我找到的最佳答案

以最快的方式获取远程IP地址。您必须使用下载程序,或在计算机上创建服务器。

使用这个简单代码的缺点:(推荐使用)是获取远程IP地址需要3-5秒,因为初始化时的WebClient始终需要3-5秒来检查您的代理设置。 / p>

<div class="container">
  <div class="col-md-12">
    <div class="row">
      <a href="#" class="logo">First</a>
      <nav class="main_menu clearfix">
        <button class="main_menu_button hidden-md hidden-lg"><i class="fa fa-bars"></i></button>
        <ul>
          <li class="active"><a href="#"></a></li>
          <li><a href="#"></a></li>
          <li><a href="#"></a></li>
          <li><a href="#"></a></li>
          <li><a href="#"></a></li>
        </ul>
      </nav>
    </div>
  </div>
</div>

以下是我修复它的方法..(第一次仍然需要3-5秒),但之后它将始终在0-2秒内获取您的远程IP地址,具体取决于您的连接。

 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;
 }

答案 17 :(得分:2)

大多数答案都提到了解决方案中的http://checkip.dyndns.org。对我们来说,它没有成功。我们已经花了很多时间来面对Timemouts。如果您的程序依赖于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。因此避免了字符串操作。

要检查catch子句中的逻辑,可以通过点击不可用的端口来重现超时。例如:http://checkip.amazonaws.com:81/

答案 18 :(得分:2)

我发现大多数其他答案都缺乏,因为他们认为任何返回的字符串都必须是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;
    }
}

答案 19 :(得分:2)

The IPIFY API很不错,因为它可以用原始文本和JSON进行响应。它也可以做回调等。唯一的问题是它在IPv4中响应,而不是6。

答案 20 :(得分:1)

您可以使用Telnet以编程方式在路由器中查询WAN IP。

Telnet部分

Telnet部分可以使用例如this Minimalistic Telnet code作为API来完成,以便向您的路由器发送Telnet命令并获取路由器的响应。本答案的其余部分假定您以某种方式设置以发送Telnet命令并在代码中获取响应。

方法的局限性

我会预先说明,与其他方法相比,查询路由器的一个缺点是您编写的代码可能与您的路由器模型相当具体。也就是说,它可以是一种不依赖外部服务器的有用方法,无论如何,您可能希望从您自己的软件访问您的路由器用于其他目的,例如配置和控制它,使编写特定代码更有价值。

示例路由器命令和响应

以下示例不适用于所有路由器,但原则上说明了该方法。您需要更改详细信息以适合您的路由器命令和响应。

例如,让路由器显示WAN IP的方法可能是以下Telnet命令:

connection list

输出可能包含一行文本列表,每个连接一个,IP地址位于偏移量39.广域网连接的行可以从行中某处的“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;
}

答案 21 :(得分:1)

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"; }
}

使用环回作为后备,这样就不会致命地破坏。

答案 22 :(得分:1)

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;
} 

完美无缺

答案 23 :(得分:1)

我已经重构了@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();
    }
}

答案 24 :(得分:0)

我和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;
    }

答案 25 :(得分:-2)

或者这个,我认为我需要的东西很好。它来自here

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);
}

答案 26 :(得分:-2)

从C#,您可以使用Web客户端库来获取whatismyip