首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# 取得本機 IP 位址的正確姿勢

     編輯:關於C語言

前言

「如何在 C# 取得本機 IP」看似簡單,實則藏著許多坑:多網卡、IPv4/IPv6 混雜、回環位址、虛擬介面等。本文從早期 Dns.Resolve 過時 API 講起,逐步引導至現代、跨平台的最佳實踐。

過時做法(不建議使用)

// .NET Framework 1.x/2.0 風格,已標記 Obsolete
IPHostEntry host = Dns.Resolve(Environment.MachineName);
string ip = host.AddressList[0].ToString(); // 風險:可能拿到 IPv6 或 127.0.0.1

Dns.Resolve 已被標記為過時,且直接取 AddressList[0] 極不穩定,順序隨作業系統、網卡綁定順序而異。

現代標準寫法(.NET Core / .NET 5+ / .NET Framework 4.5+)

使用 Dns.GetHostEntry 搭配 LINQ 過濾,精準取得想要的 IPv4 位址。

using System;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;

public static class NetworkHelper
{
    /// 
    /// 取得第一張「啟用中、非回環、IPv4」的單播位址
    /// 
    public static string GetLocalIPv4()
    {
        var host = Dns.GetHostEntry(Dns.GetHostName());
        return host.AddressList
            .Where(ip => ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork) // IPv4
            .FirstOrDefault()?.ToString() ?? "127.0.0.1";
    }

    /// 
    /// 更穩健:透過 NetworkInterface 列舉實體網卡,排除虛擬/隧道介面
    /// 
    public static string GetPrimaryIPv4()
    {
        foreach (var ni in NetworkInterface.GetAllNetworkInterfaces())
        {
            // 忽略非啟用、回環、虛擬介面
            if (ni.OperationalStatus != OperationalStatus.Up) continue;
            if (ni.NetworkInterfaceType == NetworkInterfaceType.Loopback) continue;
            if (ni.NetworkInterfaceType == NetworkInterfaceType.Tunnel) continue;

            var ipProps = ni.GetIPProperties();
            var addr = ipProps.UnicastAddresses
                .FirstOrDefault(u => u.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork
                                  && !IPAddress.IsLoopback(u.Address));
            if (addr != null) return addr.Address.ToString();
        }
        return "127.0.0.1";
    }
}

常見應用場景與陷阱

場景建議做法避坑指南
伺服器綁定 ListenerIPAddress.Any (0.0.0.0)勿硬編碼特定 IP,除非多網卡需隔離流量
向註冊中心報告自身位址GetPrimaryIPv4()需排除 Docker、VPN、Hyper-V 虛擬網卡
顯示給使用者看列舉所有 IPv4 讓使用者選擇單網卡環境下 GetLocalIPv4() 足夠

ASP.NET Core 專屬:從 HttpContext 取得 Client IP

// 在 Controller 或 Middleware 中
var clientIp = HttpContext.Connection.RemoteIpAddress?.ToString();
// 若部署在反向代理(Nginx/IIS)後方,需啟用 ForwardedHeadersMiddleware
// 並讀取 X-Forwarded-For 標頭

總結

  • 棄用 Dns.Resolve,改用 Dns.GetHostEntry。
  • 永遠過濾 AddressFamily.InterNetwork(IPv4)並排除 IPAddress.IsLoopback。
  • 生產環境建議用 NetworkInterface 列舉實體網卡,避開虛擬介面干擾。
  • 跨平台(Linux/Container)時,Dns.GetHostName() 回傳的主機名可能對應不到正確 IP,NetworkInterface 方式最穩健。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved