萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 網路安全 >  >> 網路基礎知識

C# 檢測網絡連接狀態的 3 種方案:WinINET API、NetworkInterface、HttpClient 實戰對比

在 C# / .NET 應用中判斷「當前是否聯網」,看似簡單實則坑多:NetworkInterface.GetIsNetworkAvailable() 只看介面卡狀態不檢測真實互聯網連通性;Ping 可能被防火牆封鎖;HttpClient 請求外網引入依賴與延遲。本文對比 WinINET API (系統級)、NetworkInterface + Ping (框架級)、HttpClient/HTTP 請求 (應用級) 三大方案,提供生產級代碼模板與選型建議。

方案一:WinINET API — `InternetGetConnectedState` (系統級、最輕量、無依賴)

調用 Windows 核心 `wininet.dll` 導出函數,直接讀取系統維護的連接狀態標誌 (包含調制解調器、LAN、代理、離線模式等)。

完整代碼 (可直接複製到項目)


using System;
using System.Runtime.InteropServices;

namespace NetworkUtils
{
    public static class WinInetDetector
    {
        // 導入 wininet.dll
        [DllImport("wininet.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern bool InternetGetConnectedState(out int lpdwFlags, int dwReserved);

        // 連接狀態標誌位 (部分常用)
        [Flags]
        public enum ConnectionState : int
        {
            INTERNET_CONNECTION_MODEM = 0x01,           // 調製解調器
            INTERNET_CONNECTION_LAN = 0x02,             // 區域網路
            INTERNET_CONNECTION_PROXY = 0x04,           // 代理
            INTERNET_CONNECTION_MODEM_BUSY = 0x08,      // Modem 忙
            INTERNET_RAS_INSTALLED = 0x10,              // RAS 安裝
            INTERNET_CONNECTION_OFFLINE = 0x20,         // 離線模式
            INTERNET_CONNECTION_CONFIGURED = 0x40       // 已配置連線
        }

        /// 
        /// 檢測是否有活躍的網際網路連線 (系統級判斷)
        /// 
        /// true: 系統認為有連線; false: 離線/無連線
        public static bool IsConnectedToInternet()
        {
            int flags = 0;
            try
            {
                bool result = InternetGetConnectedState(out flags, 0);
                // 可選:解析 flags 判斷具體連線類型
                // Console.WriteLine($"Flags: {(ConnectionState)flags}");
                return result;
            }
            catch (Exception ex)
            {
                // 記錄日誌
                return false;
            }
        }

        /// 
        /// 獲取詳細連線類型標誌
        /// 
        public static ConnectionState GetConnectionFlags()
        {
            int flags = 0;
            InternetGetConnectedState(out flags, 0);
            return (ConnectionState)flags;
        }
    }
}

調用示例


bool online = WinInetDetector.IsConnectedToInternet();
Console.WriteLine($"系統級聯網狀態: {online}");
if (online)
{
    var flags = WinInetDetector.GetConnectionFlags();
    Console.WriteLine($"連線類型: {flags}");
    if (flags.HasFlag(WinInetDetector.ConnectionState.INTERNET_CONNECTION_LAN))
        Console.WriteLine("-> 區域網路連接");
    if (flags.HasFlag(WinInetDetector.ConnectionState.INTERNET_CONNECTION_PROXY))
        Console.WriteLine("-> 通過代理上網");
}

優缺點分析

優點缺點
零依賴、極快 (微秒級)、無網路封包發送、系統級權威、可識別代理/離線模式/調制解調器僅反映「系統認為有連線」,不保證能訪問互聯網 (如:連著路由器但路由器斷網、Portal 認證頁、企業內網無外網權限),會有誤報「在線」

方案二:`NetworkInterface` + `Ping` — 框架級、輕量、可驗證真實通達性


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

public static class NetworkDetector
{
    /// 
    /// 綜合判斷:介面卡 UP + 能 Ping 通可靠公共節點
    /// 
    public static bool IsInternetAvailable(string host = "114.114.114.114", int timeoutMs = 3000)
    {
        // 1. 快速檢查:至少有一張非回環、非隧道、運作狀態 Up 的介面卡
        if (!NetworkInterface.GetIsNetworkAvailable())
            return false;

        foreach (var ni in NetworkInterface.GetAllNetworkInterfaces())
        {
            if (ni.OperationalStatus != OperationalStatus.Up) continue;
            if (ni.NetworkInterfaceType == NetworkInterfaceType.Loopback) continue;
            if (ni.NetworkInterfaceType == NetworkInterfaceType.Tunnel) continue; // Teredo/6to4/VPN 虛擬介面
            // 可選:過濾虛擬機/虛擬適配器 (名稱含 "Virtual", "VMware", "Hyper-V", "Docker")
            if (ni.Description.IndexOf("Virtual", StringComparison.OrdinalIgnoreCase) >= 0) continue;
            if (ni.Description.IndexOf("VMware", StringComparison.OrdinalIgnoreCase) >= 0) continue;

            // 2. 深度檢測:Ping 可靠公共 DNS (UDP/TCP 53 不通用,這裡用 ICMP)
            try
            {
                using (var ping = new Ping())
                {
                    var reply = ping.Send(host, timeoutMs);
                    if (reply.Status == IPStatus.Success)
                        return true; // 真正通往互聯網
                }
            }
            catch { /* 忽略 Ping 異常 */ }
        }
        return false;
    }

    /// 
    /// 異步版本 (避免阻塞 UI 線程)
    /// 
    public static async Task IsInternetAvailableAsync(string host = "114.114.114.114", int timeoutMs = 3000)
    {
        if (!NetworkInterface.GetIsNetworkAvailable()) return false;
        try
        {
            using (var ping = new Ping())
            {
                var reply = await ping.SendPingAsync(host, timeoutMs);
                return reply.Status == IPStatus.Success;
            }
        }
        catch { return false; }
    }
}

優缺點分析

優點缺點
純 .NET 標準庫、跨平台 (Win/Linux/macOS .NET Core/5+)、可驗證真實 IP 通達性、可自定義目標/超時、支援異步ICMP 可能被防火牆/路由器/運營商封禁/限流導致誤判「離線」;需選擇高可用測試目標 (多 IP 輪詢)

方案三:`HttpClient` 請求 HTTP/HTTPS 端點 — 應用級、最真實、支援 Proxy/認證/重試


using System.Net.Http;
using System.Threading.Tasks;

public static class HttpDetector
{
    private static readonly HttpClient _client = new HttpClient
    {
        Timeout = TimeSpan.FromSeconds(5)
    };

    // 靜態構造函數配置 (僅執行一次)
    static HttpDetector()
    {
        _client.DefaultRequestHeaders.ConnectionClose = false; // Keep-Alive
        _client.DefaultRequestHeaders.UserAgent.ParseAdd("NetworkHealthCheck/1.0");
    }

    /// 
    /// 請求可靠的 HTTP 端點驗證真實應用層連通性
    /// 
    public static async Task IsInternetReachableAsync(
        string url = "https://www.msftconnecttest.com/redirect", // 微軟 NCSI 端點,返回 200 OK
        HttpCompletionOption completionOption = HttpCompletionOption.ResponseHeadersRead)
    {
        try
        {
            using (var request = new HttpRequestMessage(HttpMethod.Head, url))
            {
                var response = await _client.SendAsync(request, completionOption);
                return response.IsSuccessStatusCode; // 2xx
            }
        }
        catch (HttpRequestException)
        {
            return false;
        }
        catch (TaskCanceledException) // Timeout
        {
            return false;
        }
    }

    /// 
    /// 多端點輪詢策略 (提高可靠性)
    /// 
    public static async Task IsInternetReachableMultiAsync()
    {
        var endpoints = new[]
        {
            "https://www.msftconnecttest.com/redirect",      // 微軟 NCSI
            "https://connect.rom.miui.com/generate_204",     // 小米/Android 檢測端點
            "https://captive.apple.com/hotspot-detect.html", // Apple
            "https://www.google.com/generate_204",          // Google (HTTPS)
            "https://www.baidu.com/"                        // 國內備用
        };

        var tasks = endpoints.Select(url => IsInternetReachableAsync(url)).ToArray();
        var results = await Task.WhenAll(tasks);
        return results.Any(r => r); // 任一成功即視為在線
    }
}

推薦測試端點 (NCSI - Network Connectivity Status Indicator)

  • https://www.msftconnecttest.com/redirect (微軟官方,返回 200 + 頁面含 "Microsoft NCSI")
  • https://msftconnecttest.com/connecttest.txt (返回 "Microsoft NCSI")
  • https://connect.rom.miui.com/generate_204 (小米/安卓標準,返回 204 No Content)
  • https://captive.apple.com/hotspot-detect.html (蘋果,返回 "Success")
  • https://www.google.com/generate_204 (Google,204)

優勢: 走真實 HTTP/TCP/TLS 棧,驗證 DNS 解析、TCP 握手、TLS 協商、HTTP 協議、代理穿透、Portal 認證攔截 — 最貼近用戶實際體驗。

優缺點分析

優點缺點
應用層真實驗證、支援 HTTPS/TLS/代理/重試/超時控制、跨平台 .NET Core/5+、可攜帶業務邏輯 (如檢查 API 健康)依賴 HttpClient/SSL/TLS 堆疊、較重 (首次冷啟動較慢)、需網路往返 (百毫秒級)、外部端點可用性依賴

四、生產環境選型建議:分級檢測策略


// 推薦組合:快速預檢 (WinINET) + 深度驗證 (Ping/HttpClient)
public static class NetworkHealth
{
    public static async Task CheckAsync()
    {
        // Level 1: 系統級極速預檢 (微秒)
        if (!WinInetDetector.IsConnectedToInternet())
            return NetworkStatus.Offline; // 系統級離線 (飛行模式/禁用網卡/拔網線)

        // Level 2: ICMP 深度檢測 (10-50ms)
        if (await NetworkDetector.IsInternetAvailableAsync())
            return NetworkStatus.Online;  // 真實 IP 通達

        // Level 3: HTTP 應用層驗證 (50-500ms) - 針對 Portal/代理/僅 HTTP 通的場景
        if (await HttpDetector.IsInternetReachableMultiAsync())
            return NetworkStatus.PortalOrRestricted; // 可能需 Web 認證/僅 HTTP 白名單

        return NetworkStatus.Offline;
    }
}

public enum NetworkStatus { Online, PortalOrRestricted, Offline }

五、常見坑與避雷指南

  • 別只信 `NetworkInterface.GetIsNetworkAvailable()`: 虛擬機/VPN/虛擬適配器/已連路由器但斷網 都會返回 true。
  • 別只 Ping 一個 IP: 目標可能單點故障。多 IP 輪詢/並發 (如 114.114.114.114、8.8.8.8、223.5.5.5、1.1.1.1)。
  • 別在 UI 線程同步 Ping/Http: 必須用 `async/await` / `Task.Run`,否則界面卡死。
  • 緩存結果: 同一秒內多次檢測返回緩存結果,避免風暴請求。
  • 處理網路變更事件: `NetworkChange.NetworkAvailabilityChanged` / `NetworkAddressChanged` 事件觸發重新檢測,更新 UI 狀態圖示。

C# 檢測網絡狀態,沒有銀彈,只有分級組合。WinINET 看系統認知、Ping 看 IP 通達、HttpClient 看應用層真實可用。根據業務敏感度 (即時通訊/交易/後台同步/離線優先) 選擇合適層級或組合,並做好緩存、異步、多端點容錯,才能構建健壯的網絡感知能力。

copyright © 萬盛學電腦網 all rights reserved