【问题标题】:Get local IP address of interface used to make a web service call within a Windows service获取用于在 Windows 服务中进行 Web 服务调用的接口的本地 IP 地址
【发布时间】:2026-02-05 05:20:05
【问题描述】:

我们正在开发要安装在客户端系统上的 Windows 服务。此应用程序定期调用我们服务器上的 SOAP Web 服务。我们希望在每次访问我们的服务时将客户端系统的本地 IP 地址包含在 SOAP 请求中以进行故障排除。浏览此处的其他帖子,我发现以下代码可以获取系统上接口的 IP 列表:

IPAddress[] localIPs = Dns.GetHostAddresses(Dns.GetHostName());

此代码包含在 Windows 服务中。是否有一种简单的方法来确定此数组中的哪个 IP 分配给路由 Web 服务调用的接口?

【问题讨论】:

  • 并非如此——路由是在构建请求之后发生的。您可以做的最好的事情是在服务器端捕获请求来自的 IP,但根据路由/NAT,您可能看不到发起者的 IP。
  • @Joe,谢谢。因此,如果我使用 HttpWebRequest 对象来访问服务,是否有任何方法可以获取发送请求的接口的本地 IP?本地IP确实是我们想要的。这听起来像是一个可行的选择吗——我尝试使用 Socket 类连接到端点,然后获取套接字的 LocalEndPoint。这样做是否会冒着返回错误 IP 的风险?我认为套接字连接和服务请求可能不一定通过同一接口路由。

标签: c# .net windows-services ip-address


【解决方案1】:

如果您使用的是 WCF 3.5 或更高版本,则可以使用消息属性直接在服务中获取客户端的 IP 地址,如blog 中的代码所示

【讨论】:

  • 谢谢。我应该提到客户端没有访问 WCF 服务。我们不想在他们访问的服务中捕获 IP 地址,因为我们想确保我们正在记录发出请求的系统的本地 IP。有没有办法在客户端运行的长期运行的 Windows 服务中确定这一点?
【解决方案2】:

您可以在您的 Windows 服务中运行以下代码来获取盒子上任何接口的 IP。

/// <summary>
/// Returns the IP Address of the given interface
/// </summary>
/// <param name="InterfaceName">Name of the interface</param>
/// <param name="AddressFamily">Address family to search for</param>
/// <returns>IPAddress of assinged IP address</returns>
public IPAddress GetIPAddress(string InterfaceName, System.Net.Sockets.AddressFamily AddressFamily)
{
    System.Net.NetworkInformation.NetworkInterface Interface = GetInterface(InterfaceName);
    if (Interface != null)
    {
        foreach (System.Net.NetworkInformation.UnicastIPAddressInformation IP in Interface.GetIPProperties().UnicastAddresses) 
        {
            //Match address family
            if(IP.Address.AddressFamily != AddressFamily)
                continue;

            //Check for IPv6 conditions since we can easily have multiple IPs
            if(IP.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6 && (IP.Address.IsIPv6LinkLocal || IP.AddressPreferredLifetime != uint.MaxValue || IP.AddressValidLifetime != uint.MaxValue))
                continue;

            //We've found the IP
            return IP.Address;
        }
    }

    return null;
}

/// <summary>
/// Returns the Network Interface for the given windows name
/// </summary>
/// <param name="InterfaceName">Interface name to get (ie Local Area Connection)</param>
/// <returns>Network Interface, or null if not found</returns>
System.Net.NetworkInformation.NetworkInterface GetInterface(string InterfaceName)
{
    if (InterfaceName == null || InterfaceName.Length == 0)
        return null;

    foreach (System.Net.NetworkInformation.NetworkInterface Interface in NetworkInterfaceArray)
    {
        if (Interface.Name == InterfaceName)
            return Interface;
    }

    return null;
}

【讨论】:

  • 谢谢。是否可以添加任何其他逻辑来确定使用哪个接口来访问 Web 服务?我们希望获得一个发起请求的本地 IP。
【解决方案3】:

返回一个列表,其中包含运行它的机器上的 IP,只要适配器启动而不是环回接口。

public static List<string> DisplayDnsAddresses()
{
    var addresses = NetworkInterface.GetAllNetworkInterfaces()
        .Where(a => a.OperationalStatus == OperationalStatus.Up
                    && a.NetworkInterfaceType != NetworkInterfaceType.Loopback)
        .Select(a => a.GetIPProperties())
        .SelectMany(ipp => ipp.UnicastAddresses
            .Select(x => x.Address.ToString()));

    return addresses.ToList();
}

这可能需要稍微改进一下。我不确定如何确定 Web 服务将使用哪个接口,但如果您知道必须用于访问您的网络的网关,也许您可​​以将其固定。

【讨论】:

  • 感谢您的建议,我会进一步研究,看看这是否是确定 Web 服务正在使用哪个接口的可行方法。