获取公网/外网IP地址?

94

我似乎找不到有关查找我的路由器公共IP的信息?这是因为无法通过这种方式完成,必须从网站获取吗?


"这边是哪边?你是想通过编程实现这个吗?" - Marcelo Cantos
1
使用CGN,您的路由器可能没有公共地址。 - Ron Maupin
29个回答

138
使用C#,利用异步方法使用HTTPClient。
public static async Task<IPAddress?> GetExternalIpAddress()
{
    var externalIpString = (await new HttpClient().GetStringAsync("http://icanhazip.com"))
        .Replace("\\r\\n", "").Replace("\\n", "").Trim();
    if(!IPAddress.TryParse(externalIpString, out var ipAddress)) return null;
    return ipAddress;
}

public static void Main(string[] args)
{
    var externalIpTask = GetExternalIpAddress();
    GetExternalIpAddress().Wait();
    var externalIpString = externalIpTask.Result ?? IPAddress.Loopback;

    Console.WriteLine(externalIpString);
}

过时的 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

curl http://ipinfo.io/ip

第二个出现了404错误。 - Ronnie Overby
10
好的回答!顺便说一下,我必须在从http://ipinfo.io/ip得到的结果上调用Trim()。有一个尾随空格。 - Nicholas Miller
4
这将获取服务器的IP地址,而不是用户的。 - Paul
解析IP地址与直接输出“externalIpString”的好处是什么? - Stewart
1
输入验证,您还可以在需要此类输入的其他方法中使用IPAddress。 - CodeOrElse

74
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不存在,有什么替代方案吗? - Kiquenet

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

错误:请求被中止:无法创建SSL/TLS安全通道。 - Lê Vũ Huy

41

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

29

使用一个非常相似的服务

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

1
ifconfig.me 这个域名非常完美。 - yurenchen
私有字符串 GetPublicIpAddress() { 使用 var 客户端 = new WebClient(); 返回客户端.DownloadString("http://ifconfig.me").Replace("\n", ""); } - Marcelo Vieira
1
一个更现代的替代方案:public static string GetPublicIPv4Address() => new System.Net.Http.HttpClient().GetStringAsync("http://ifconfig.me").GetAwaiter().GetResult().Replace("\n", ""); - absoluteAquarian

25

在@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 对象。以下是一些这样的服务*:

* 这个问题提到了一些服务,并且从这些超级用户网站的答案中得出结论。


2
在前面添加 https 得分加一。我不知道为什么这里的大多数人认为通过 http 请求外部 IP 是正常的。顺便说一下,checkip.amazonaws.com 现在支持 SSL。 - Marinos An

17

理论上,您的路由器应该能够告诉您网络的公共IP地址,但这种方法可能是不一致/不直观的,甚至有些路由器设备可能无法做到。

最简单而且非常可靠的方法是向返回您的IP地址的网页发送请求。Dyndns.org为此提供了良好的服务:

http://checkip.dyndns.org/

返回的是一个极其简单/短的HTML文档,包含文本Current IP Address: 157.221.82.39(虚假IP),从HTTP响应中提取这些信息十分容易。


没关系。我只是说因为新成员经常不熟悉系统...谢谢。 - Noldorin
1
如果ISP使用CGN,那么这实际上无法获取路由器地址。它只会获取ISP路由器地址。 - Ron Maupin

9
我发现http://checkip.dyndns.org/ 给我的是需要处理的html标签,而https://icanhazip.com/ 则给了我一个简单的字符串。不幸的是,https://icanhazip.com/ 给了我IPv6地址,而我需要IPv4地址。幸运的是,这里有两个子域名可供选择,ipv4.icanhazip.com 和 ipv6.icanhazip.com。
        string externalip = new WebClient().DownloadString("https://ipv4.icanhazip.com/");
        Console.WriteLine(externalip);
        Console.WriteLine(externalip.TrimEnd());

这是最好的方式,它有效且代码短小! - Emanuel Pirovano
很棒的解决方案,但它依赖于其他一些外部服务。找到另外几个类似的服务并用作备选方案会更好。例如:https://api.ipify.org/ 和 https://www.trackip.net/ip - Kosta_M

6

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

 }

希望这对你有所帮助。

这里 是一个包含此代码的应用程序示例。


3
不能 失败! :) - thepirat000

6

只需几行代码,您就可以编写自己的Http服务器。

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循环中,什么时候会出现这种情况? - ossentoo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接