การเช็ค Internet Connectivity ใน C# มีหลายวิธี ขึ้นอยู่กับความแม่นยำและ Use Case
วิธีที่ 1: HttpClient / WebClient (Real Connectivity Test - แนะนำ)
ทดสอบจริงโดย Request ไปยัง Endpoint ที่เชื่อถือได้
using System;
using System.Net.Http;
using System.Threading.Tasks;
public static class ConnectivityChecker
{
private static readonly HttpClient _httpClient = new HttpClient
{
Timeout = TimeSpan.FromSeconds(5)
};
// Google Generate 204 - Endpoint มาตรฐานสำหรับ Captive Portal Detection
private const string TestUrl = "https://www.google.com/generate_204";
public static async Task IsConnectedAsync()
{
try
{
using var response = await _httpClient.GetAsync(TestUrl, HttpCompletionOption.ResponseHeadersRead);
return response.StatusCode == System.Net.HttpStatusCode.NoContent; // 204
}
catch
{
return false;
}
}
// Synchronous Version (สำหรับ Legacy/Console)
public static bool IsConnected()
{
try
{
using var client = new System.Net.WebClient();
using var stream = client.OpenRead(TestUrl);
return true;
}
catch
{
return false;
}
}
}
// ใช้งาน
static async Task Main()
{
bool connected = await ConnectivityChecker.IsConnectedAsync();
Console.WriteLine($"Internet: {(connected ? "Connected" : "Disconnected")}");
}
วิธีที่ 2: NetworkInterface (Local Network Only - ไม่ใช่ Internet)
using System.Net.NetworkInformation;
public static bool IsNetworkAvailable()
{
return NetworkInterface.GetIsNetworkAvailable();
}
// รายละเอียด
public static void PrintNetworkStatus()
{
if (!NetworkInterface.GetIsNetworkAvailable())
{
Console.WriteLine("No Network Interface Up");
return;
}
foreach (var ni in NetworkInterface.GetAllNetworkInterfaces())
{
if (ni.OperationalStatus == OperationalStatus.Up)
{
Console.WriteLine($"Interface: {ni.Name} ({ni.NetworkInterfaceType})");
Console.WriteLine($" Speed: {ni.Speed / 1_000_000} Mbps");
Console.WriteLine($" IPv4: {ni.GetIPProperties().UnicastAddresses.FirstOrDefault(a => a.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)?.Address}");
}
}
}
⚠️ NetworkInterface.GetIsNetworkAvailable() คืน True หากมี NIC ใด NIC หนึ่ง Up แม้จะไม่มี Internet (เช่น Connected to LAN Only)
วิธีที่ 3: Ping (ICMP - ไม่เสมอไปที่ทำงาน)
public static bool PingHost(string host = "8.8.8.8", int timeout = 3000)
{
try
{
using var ping = new Ping();
PingReply reply = ping.Send(host, timeout);
return reply.Status == IPStatus.Success;
}
catch
{
return false;
}
}
⚠️ หลาย Network/Firewall Block ICMP → False Negative
วิธีที่ 4: Continuous Monitoring (Retry Loop)
public static async Task WaitForInternetAsync(TimeSpan? timeout = null, TimeSpan? retryInterval = null)
{
var cts = timeout.HasValue ? new CancellationTokenSource(timeout.Value) : new CancellationTokenSource();
var interval = retryInterval ?? TimeSpan.FromSeconds(5);
while (!cts.Token.IsCancellationRequested)
{
if (await IsConnectedAsync())
{
Console.WriteLine("Internet connected!");
return;
}
Console.WriteLine("No internet, retrying...");
try { await Task.Delay(interval, cts.Token); }
catch (OperationCanceledException) { break; }
}
throw new TimeoutException("Timed out waiting for internet connection");
}
Best Practices
- ใช้ HTTP/HTTPS Endpoint (Port 80/443) แทน Ping (ICMP) เพราะ Firewall มัก Block ICMP
- Endpoint ควรเป็น Generate 204 (No Content, Fast, Standard)
- ตั้ง Timeout สั้น (3-5 วินาที) ป้องกัน Hang
- ใช้
HttpCompletionOption.ResponseHeadersReadไม่ต้อง Download Body - Handle
TaskCanceledException(Timeout) และHttpRequestException - ใน Mobile/Xamarin/MAUI: ใช้
ConnectivityPlugin (Xamarin.Essentials / MAUI Essentials)
ใน ASP.NET Core Health Checks
// Startup.cs
services.AddHealthChecks()
.AddUrlGroup(new Uri("https://www.google.com/generate_204"), "internet-check",
timeout: TimeSpan.FromSeconds(5));
// หรือ Custom Health Check
public class InternetHealthCheck : IHealthCheck
{
public async Task CheckHealthAsync(HealthCheckContext context, CancellationToken ct = default)
{
bool connected = await ConnectivityChecker.IsConnectedAsync();
return connected ? HealthCheckResult.Healthy() : HealthCheckResult.Unhealthy("No internet");
}
}