You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C#控制台程序中不依赖第三方网站获取用户公网IP?

不依赖第三方网站获取公网IP的C#实现

首先要明确:本地主机本身并没有直接持有公网IP——公网IP通常分配给你网络出口的NAT设备(比如家用路由器、企业网关)。所以不依赖第三方网站的话,只能通过与这个NAT设备交互来获取公网IP,最常用的方式是利用UPnP(通用即插即用)协议,多数家用路由器默认开启了UPnP支持。

以下是基于UPnP协议的实现代码:

using System;
using System.Net;
using System.Net.Sockets;
using System.Xml.Linq;

class PublicIpFetcher
{
    static void Main(string[] args)
    {
        string publicIp = GetPublicIpViaUpnp();
        if (!string.IsNullOrEmpty(publicIp))
        {
            Console.WriteLine($"公网IP: {publicIp}");
        }
        else
        {
            Console.WriteLine("无法获取公网IP,可能是路由器未开启UPnP,或者设备不支持UPnP协议。");
        }
    }

    static string GetPublicIpViaUpnp()
    {
        try
        {
            // 发送UPnP服务发现的UDP广播请求
            string discoveryRequest = @"M-SEARCH * HTTP/1.1
HOST: 239.255.255.250:1900
MAN: ""ssdp:discover""
MX: 3
ST: urn:schemas-upnp-org:service:WANIPConnection:1";

            using UdpClient udpClient = new UdpClient();
            udpClient.EnableBroadcast = true;
            IPEndPoint multicastEndpoint = new IPEndPoint(IPAddress.Parse("239.255.255.250"), 1900);
            byte[] requestBytes = System.Text.Encoding.ASCII.GetBytes(discoveryRequest);
            udpClient.Send(requestBytes, requestBytes.Length, multicastEndpoint);

            // 接收路由器返回的服务信息
            IPEndPoint responseEndpoint = new IPEndPoint(IPAddress.Any, 0);
            byte[] responseBytes = udpClient.Receive(ref responseEndpoint);
            string response = System.Text.Encoding.ASCII.GetString(responseBytes);

            // 从响应中提取UPnP服务的控制URL
            string[] responseLines = response.Split(new[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
            string controlUrl = null;
            foreach (string line in responseLines)
            {
                if (line.StartsWith("LOCATION:"))
                {
                    string locationUrl = line.Substring(9).Trim();
                    using WebClient client = new WebClient();
                    string deviceXml = client.DownloadString(locationUrl);
                    XDocument doc = XDocument.Parse(deviceXml);
                    XNamespace ns = "urn:schemas-upnp-org:device-1-0";
                    var service = doc.Descendants(ns + "service")
                                     .FirstOrDefault(s => s.Element(ns + "serviceType")?.Value == "urn:schemas-upnp-org:service:WANIPConnection:1");
                    if (service != null)
                    {
                        string relativeControlUrl = service.Element(ns + "controlURL")?.Value;
                        if (!string.IsNullOrEmpty(relativeControlUrl))
                        {
                            Uri locationUri = new Uri(locationUrl);
                            controlUrl = new Uri(locationUri, relativeControlUrl).ToString();
                        }
                        break;
                    }
                }
            }

            if (string.IsNullOrEmpty(controlUrl))
                return null;

            // 发送SOAP请求获取公网IP
            string soapRequest = @"<?xml version=""1.0"" encoding=""utf-8""?>
<s:Envelope xmlns:s=""http://schemas.xmlsoap.org/soap/envelope/"" s:encodingStyle=""http://schemas.xmlsoap.org/soap/encoding/"">
  <s:Body>
    <u:GetExternalIPAddress xmlns:u=""urn:schemas-upnp-org:service:WANIPConnection:1"" />
  </s:Body>
</s:Envelope>";

            WebRequest webRequest = WebRequest.Create(controlUrl);
            webRequest.Method = "POST";
            webRequest.ContentType = "text/xml; charset=utf-8";
            webRequest.Headers.Add("SOAPAction", "\"urn:schemas-upnp-org:service:WANIPConnection:1#GetExternalIPAddress\"");

            using (var stream = webRequest.GetRequestStream())
            {
                byte[] soapBytes = System.Text.Encoding.UTF8.GetBytes(soapRequest);
                stream.Write(soapBytes, 0, soapBytes.Length);
            }

            using WebResponse webResponse = webRequest.GetResponse();
            using var reader = new System.IO.StreamReader(webResponse.GetResponseStream());
            string soapResponse = reader.ReadToEnd();
            XDocument soapDoc = XDocument.Parse(soapResponse);
            XNamespace soapNs = "http://schemas.xmlsoap.org/soap/envelope/";
            XNamespace uNs = "urn:schemas-upnp-org:service:WANIPConnection:1";
            var ipElement = soapDoc.Descendants(soapNs + "Body")
                                   .FirstOrDefault()?
                                   .Descendants(uNs + "GetExternalIPAddressResponse")
                                   .FirstOrDefault()?
                                   .Element(uNs + "NewExternalIPAddress");
            return ipElement?.Value;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"获取失败: {ex.Message}");
            return null;
        }
    }
}

注意事项

  • 该代码依赖路由器开启UPnP功能,若路由器未开启则无法获取公网IP
  • 部分企业网络可能禁用UPnP,这种情况下该方法无效
  • 运行程序需要确保有足够的网络权限(比如允许UDP广播、HTTP请求)

内容的提问来源于stack exchange,提问作者ch0ck

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 10:05:22