【问题标题】:Get public/external IP address?获取公共/外部 IP 地址?
【发布时间】:2011-03-16 06:51:23
【问题描述】:

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

【问题讨论】:

  • “这条路”是哪条路?您是否尝试以编程方式执行此操作?
  • 使用 CGN,您的路由器可能没有公共地址。

标签: c# networking ip-address


【解决方案1】:

使用 C#,使用 webclient 很短。

public static void Main(string[] args)
{
    string externalIpString = new WebClient().DownloadString("http://icanhazip.com").Replace("\\r\\n", "").Replace("\\n", "").Trim();
    var externalIp = IPAddress.Parse(externalIpString);

    Console.WriteLine(externalIp.ToString());
}

命令行(适用于 Linux 和 Windows)

wget -qO- http://bot.whatismyipaddress.com

curl http://ipinfo.io/ip

【讨论】:

  • 第二个是 404。
  • 很好的答案!顺便说一句,我不得不在http://ipinfo.io/ip 的结果上调用Trim()。有一个尾随空格。
  • 这将获得服务器的 IP 地址,而不是用户的。
  • 解析IP地址,而不是直接输出externalIpString有什么好处?
【解决方案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;
    }
}

【讨论】:

  • 如果 ISP 使用 CGN(越来越普遍),这实际上无法获取路由器地址。它只会获取 ISP 路由器地址,而不是分配给您的路由器的地址。
  • @RonMaupin 没有人在谈论实际的路由器地址。问题是你在互联网上的 IP 是什么。
【解决方案3】:

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

【讨论】:

    【解决方案4】:

    通过@suneel ranga扩展此answer

    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 中提到了一些服务。

    【讨论】:

    • +1 用于在前面添加https。我不知道为什么这里的大多数人认为通过http 请求外部IP 是正常的。顺便说一句 checkip.amazonaws.com 现在支持 ssl。
    【解决方案5】:
    private static string GetPublicIpAddress()
    {
        using (var client = new WebClient())
        {
           return client.DownloadString("http://ifconfig.me").Replace("\n", "");
        }
    }
    

    【讨论】:

      【解决方案6】:

      使用很棒的类似服务

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

      【讨论】:

      • ifconfig.me 这个域名是完美的
      • 私有字符串 GetPublicIpAddress() { using var client = new WebClient(); return client.DownloadString("ifconfig.me").Replace("\n", ""); }
      【解决方案7】:

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

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

      的信息

      解释

      所有在线服务都返回外部IP地址, 但这并不意味着这个地址被分配给用户的路由器。

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

      查看路由器是否有外部IP的方法如下:

      根据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 地址:

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


      解决方案

      1. 使用Ttl = 2 Ping 到某个地址
      2. 评估响应的来源。

      TTL=2 必须不足以到达远程主机。跃点 #1 主机将发出 "Reply from &lt;ip address&gt;: 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;
      }
      

      【讨论】:

        【解决方案8】:

        我已将@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();
            }
        }
        

        【讨论】:

        【解决方案9】:

        我发现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());
        

        【讨论】:

        • 这是最好的方法,它有效而且是短代码!
        • 很好的解决方案,但是,它依赖于其他一些外部服务。找到其他几个类似的服务并用作后备服务会很棒。例如。 api.ipify.orgtrackip.net/ip
        【解决方案10】:

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

        【讨论】:

          【解决方案11】:

          基本上,如果其中一个 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),例如我使用此代码的一些标签

           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】:
          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

          【讨论】:

          • HttpGet 不存在,替代?
          【解决方案13】:

          大多数答案在解决方案中都提到了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/

          【讨论】:

            【解决方案14】:

            我找到的最佳答案

            以最快的方式获取远程 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;
            }
            

            【讨论】:

              【解决方案15】:

              您可以使用Telnet 以编程方式查询您的路由器以获取 WAN IP。

              Telnet 部分

              Telnet 部分可以使用例如this Minimalistic Telnet code 作为 API 来完成,以向您的路由器发送 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 的代码

              (假设您有一个用于 Telnet 部分的方法 sendRouterCommand — 见上文。

              使用上述示例路由器,以下代码获取 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;
              }
              

              【讨论】:

                【解决方案16】:
                string pubIp =  new System.Net.WebClient().DownloadString("https://api.ipify.org");
                

                【讨论】:

                  【解决方案17】:
                  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"; }
                  }
                  

                  使用环回作为后备,这样事情就不会致命地中断。

                  【讨论】:

                    【解决方案18】:
                    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;
                    } 
                    

                    完美运行

                    【讨论】:

                    • 您能补充一些评论吗?
                    • 它不起作用。 ServerVariables 成员抛出空引用异常。
                    • 这似乎是查找远程客户端 ip 的代码,而不是您的客户端公共 ip。
                    【解决方案19】:

                    我使用来自System.Net.HttpHttpClient 来做到这一点:

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

                    【讨论】:

                      【解决方案20】:

                      或者这个,它工作得很好,我认为我需要什么。来自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);
                      }
                      

                      【讨论】:

                        【解决方案21】:

                        无需任何连接即可快速获取外部 ip 实际上不需要任何 Http 连接

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

                        【讨论】:

                        • 要使 NATUPNPLib 工作,需要在路由器中启用 UPnP,即security issue
                        【解决方案22】:

                        checkip.dyndns.org 并不总是正常工作。例如,对于我的机器,它显示内部 NAT 后地址:

                        Current IP Address: 192.168.1.120
                        

                        我认为它正在发生,因为我的本地 DNS 区域位于 NAT 后面,并且我的浏览器 发送到 checkip 其本地 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 客户端库,例如,这里:

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

                        然后使用它。

                        【讨论】:

                          【解决方案23】:

                          当我调试时,我使用以下来构造外部可调用的 URL,但您可以只使用前 2 行来获取您的公共 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 而不是使用WebRequest 的获取请求要快得多。我可以确认这就像一个魅力。
                          【解决方案24】:

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

                          【讨论】:

                            【解决方案25】:

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

                            【讨论】:

                            • 这个什么时候存在,有那个while循环?
                            【解决方案26】:

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

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

                            http://checkip.dyndns.org/

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

                            【讨论】:

                            • 不用担心。我只是说因为新成员经常不熟悉系统...谢谢。
                            • 如果 ISP 使用 CGN,这实际上无法获取路由器地址。它只会获取 ISP 路由器地址。
                            猜你喜欢
                            • 1970-01-01
                            • 2017-09-23
                            • 1970-01-01
                            • 2021-11-20
                            • 2013-04-03
                            • 2016-03-10
                            • 2018-10-22
                            • 1970-01-01
                            相关资源
                            最近更新 更多