¿Cuál es la mejor manera de verificar la conectividad a Internet usando .NET?

¿Cuál es la forma más rápida y eficiente de verificar la conectividad a Internet en .NET?

    Algo como esto debería funcionar.

    System.Net.WebClient

    public static bool CheckForInternetConnection() { try { using (var client = new WebClient()) using (client.OpenRead("http://clients3.google.com/generate_204")) { return true; } } catch { return false; } } 

    No hay forma de que pueda verificar de manera confiable si hay una conexión a Internet o no (supongo que quiere decir acceso a Internet).

    Sin embargo, puede solicitar recursos que prácticamente nunca están fuera de línea, como hacer ping a google.com o algo similar. Creo que esto sería eficiente.

     try { Ping myPing = new Ping(); String host = "google.com"; byte[] buffer = new byte[32]; int timeout = 1000; PingOptions pingOptions = new PingOptions(); PingReply reply = myPing.Send(host, timeout, buffer, pingOptions); return (reply.Status == IPStatus.Success); } catch (Exception) { return false; } 

    En lugar de verificar, solo realice la acción (solicitud web, correo, ftp, etc.) y prepárese para que la solicitud falle, lo que debe hacer de todos modos, incluso si su cheque fue exitoso.

    Considera lo siguiente:

     1 - check, and it is OK 2 - start to perform action 3 - network goes down 4 - action fails 5 - lot of good your check did 

    Si la red no funciona, su acción fallará tan rápido como un ping, etc.

     1 - start to perform action 2 - if the net is down(or goes down) the action will fail 

    NetworkInterface.GetIsNetworkAvailable es muy poco confiable. Solo tiene algo de VMware u otra conexión LAN y devolverá el resultado incorrecto. También sobre el método Dns.GetHostEntry , me preocupaba si la URL de prueba podría estar bloqueada en el entorno en el que se implementará mi aplicación.

    Entonces, otra forma que descubrí es usando InternetGetConnectedState método InternetGetConnectedState . Mi código es

     [System.Runtime.InteropServices.DllImport("wininet.dll")] private extern static bool InternetGetConnectedState(out int Description, int ReservedValue); public static bool CheckNet() { int desc; return InternetGetConnectedState(out desc, 0); } 

    No estoy de acuerdo con las personas que afirman: “¿Qué sentido tiene verificar la conectividad antes de realizar una tarea, ya que inmediatamente después del control se puede perder la conexión?”. Seguramente hay un cierto grado de incertidumbre en muchas tareas de progtwigción que nosotros como desarrolladores llevamos a cabo, pero reducir la incertidumbre a un nivel de aceptación es parte del desafío.

    Hace poco me encontré con este problema al hacer una aplicación que incluye una función de mapeo que se vinculaba a un servidor de mosaico en línea. Esta funcionalidad debía desactivarse cuando se notaba la falta de conectividad a Internet.

    Algunas de las respuestas en esta página fueron muy buenas, pero sin embargo causaron muchos problemas de rendimiento, como la suspensión, principalmente en el caso de la ausencia de conectividad.

    Aquí está la solución que terminé usando, con la ayuda de algunas de estas respuestas y mis colegas:

      // Insert this where check is required, in my case program start ThreadPool.QueueUserWorkItem(CheckInternetConnectivity); } void CheckInternetConnectivity(object state) { if (System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable()) { using (WebClient webClient = new WebClient()) { webClient.CachePolicy = new System.Net.Cache.RequestCachePolicy(System.Net.Cache.RequestCacheLevel.BypassCache); webClient.Proxy = null; webClient.OpenReadCompleted += webClient_OpenReadCompleted; webClient.OpenReadAsync(new Uri("")); } } } volatile bool internetAvailable = false; // boolean used elsewhere in code void webClient_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e) { if (e.Error == null) { internetAvailable = true; Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() => { // UI changes made here })); } } 

    Una prueba de conexión a Internet haciendo ping a Google:

     new Ping().Send("www.google.com.mx").Status == IPStatus.Success 

    No resuelve el problema de la disminución de la red entre verificar y ejecutar el código pero es bastante confiable

     public static bool IsAvailableNetworkActive() { // only recognizes changes related to Internet adapters if (System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable()) { // however, this will include all adapters -- filter by opstatus and activity NetworkInterface[] interfaces = System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces(); return (from face in interfaces where face.OperationalStatus == OperationalStatus.Up where (face.NetworkInterfaceType != NetworkInterfaceType.Tunnel) && (face.NetworkInterfaceType != NetworkInterfaceType.Loopback) select face.GetIPv4Statistics()).Any(statistics => (statistics.BytesReceived > 0) && (statistics.BytesSent > 0)); } return false; } 

    He visto todas las opciones enumeradas anteriormente y la única opción viable para verificar si Internet está disponible o no es la opción “Ping”. Importación [DllImport("Wininet.dll")] y System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces() O cualquier otra variación de la clase NetworkInterface no funciona bien para detectar la disponibilidad de la red. Estos métodos solo comprueban si la red el cable está enchufado o no.

    La “opción Ping”

    if (La conexión está disponible) devuelve true

    if (La conexión no está disponible y el cable de red está enchufado) devuelve false

    if (El cable de red no está enchufado) Throws an exception

    The NetworkInterface

    if (Internet está disponible) Devuelve True

    if (Internet no está disponible y el cable de red está enchufado) Devuelve True

    if (el cable de red no está enchufado) devuelve false

    El [DllImport (“Wininet.dll”)]

    if (Internet está disponible) Devuelve True

    if (Internet no está disponible y el cable de red está enchufado) Devuelve True

    if (el cable de red no está enchufado) devuelve false

    Por lo tanto, en el caso de [DllImport("Wininet.dll")] y NetworkInterface no hay forma de saber si la conexión a Internet está disponible.

     private bool ping() { System.Net.NetworkInformation.Ping pingSender = new System.Net.NetworkInformation.Ping(); System.Net.NetworkInformation.PingReply reply = pingSender.Send(address); if (reply.Status == System.Net.NetworkInformation.IPStatus.Success) { return true; } else { return false; } } 

    Hacer ping a google.com introduce una dependencia de resolución DNS. Ping 8.8.8.8 está bien, pero Google está a varios pasos de distancia de mí. Todo lo que necesito hacer es hacer ping a la cosa más cercana a mí que está en internet.

    Puedo usar la función TTL de Ping para hacer ping a ping hop # 1, luego a hop # 2, etc., hasta que recibo una respuesta de algo que está en una dirección enrutable; si ese nodo está en una dirección enrutable, entonces está en internet. Para la mayoría de nosotros, el salto n. ° 1 será nuestro gateway / enrutador local, y el salto n. ° 2 será el primer punto del otro lado de nuestra conexión de fibra o lo que sea.

    Este código funciona para mí y responde más rápido que algunas de las otras sugerencias en este hilo porque está haciendo ping a lo que está más cerca de mí en Internet.

     using System.Net; using System.Net.Sockets; using System.Net.NetworkInformation; using System.Diagnostics; internal static bool ConnectedToInternet() { const int maxHops = 30; const string someFarAwayIpAddress = "8.8.8.8"; // Keep pinging further along the line from here to google // until we find a response that is from a routable address for (int ttl = 1; ttl < = maxHops; ttl++) { Ping pinger = new Ping(); PingOptions options = new PingOptions(ttl, true); byte[] buffer = new byte[32]; PingReply reply = null; try { reply = pinger.Send(someFarAwayIpAddress, 10000, buffer, options); } catch (System.Net.NetworkInformation.PingException pingex) { Debug.Print("Ping exception (probably due to no network connection or recent change in network conditions), hence not connected to internet. Message: " + pingex.Message); return false; } System.Diagnostics.Debug.Print("Hop #" + ttl.ToString() + " is " + (reply.Address == null ? "null" : reply.Address.ToString()) + ", " + reply.Status.ToString()); if (reply.Status != IPStatus.TtlExpired && reply.Status != IPStatus.Success) { Debug.Print("Hop #" + ttl.ToString() + " is " + reply.Status.ToString() + ", hence we are not connected."); return false; } if (IsRoutableAddress(reply.Address)) { System.Diagnostics.Debug.Print("That's routable so you must be connected to the internet."); return true; } } return false; } private static bool IsRoutableAddress(IPAddress addr) { if (addr == null) { return false; } else if (addr.AddressFamily == AddressFamily.InterNetworkV6) { return !addr.IsIPv6LinkLocal && !addr.IsIPv6SiteLocal; } else // IPv4 { byte[] bytes = addr.GetAddressBytes(); if (bytes[0] == 10) { // Class A network return false; } else if (bytes[0] == 172 && bytes[1] >= 16 && bytes[1] < = 31) { // Class B network return false; } else if (bytes[0] == 192 && bytes[1] == 168) { // Class C network return false; } else { // None of the above, so must be routable return true; } } } 

    Así es como se implementa en Android.

    Como una prueba de concepto, traduje este código a C #:

     var request = (HttpWebRequest)WebRequest.Create("http://g.cn/generate_204"); request.UserAgent = "Android"; request.KeepAlive = false; request.Timeout = 1500; using (var response = (HttpWebResponse)request.GetResponse()) { if (response.ContentLength == 0 && response.StatusCode == HttpStatusCode.NoContent) { //Connection to internet available } else { //Connection to internet not available } } 

    Otra opción es la API Network List Manager, que está disponible para Vista y Windows 7. Aquí se encuentra el artículo de MSDN. En el artículo hay un enlace para descargar muestras de código que le permiten hacer esto:

     AppNetworkListUser nlmUser = new AppNetworkListUser(); Console.WriteLine("Is the machine connected to internet? " + nlmUser.NLM.IsConnectedToInternet.ToString()); 

    Asegúrese de agregar una referencia a la Biblioteca de tipos de la Lista de redes 1.0 desde la pestaña COM … que se mostrará como LISTA DE REDES.

    Personalmente, encuentro mejor la respuesta de Anton y moffeltje , pero agregué un cheque para excluir las redes virtuales configuradas por VMWare y otros.

     public static bool IsAvailableNetworkActive() { // only recognizes changes related to Internet adapters if (!System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable()) return false; // however, this will include all adapters -- filter by opstatus and activity NetworkInterface[] interfaces = System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces(); return (from face in interfaces where face.OperationalStatus == OperationalStatus.Up where (face.NetworkInterfaceType != NetworkInterfaceType.Tunnel) && (face.NetworkInterfaceType != NetworkInterfaceType.Loopback) where (!(face.Name.ToLower().Contains("virtual") || face.Description.ToLower().Contains("virtual"))) select face.GetIPv4Statistics()).Any(statistics => (statistics.BytesReceived > 0) && (statistics.BytesSent > 0)); } 

    Si desea notificar al usuario / tomar medidas cada vez que ocurra un cambio de red / conexión.
    Use NLM API:

    No creo que sea imposible, simplemente no sencillo.

    Construí algo como esto, y sí, no es perfecto, pero el primer paso es esencial: verificar si hay conectividad de red. Windows Api no hace un gran trabajo, entonces ¿por qué no hacer un mejor trabajo?

     bool NetworkIsAvailable() { var all = System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces(); foreach (var item in all) { if (item.NetworkInterfaceType == NetworkInterfaceType.Loopback) continue; if (item.Name.ToLower().Contains("virtual") || item.Description.ToLower().Contains("virtual")) continue; //Exclude virtual networks set up by VMWare and others if (item.OperationalStatus == OperationalStatus.Up) { return true; } } return false; } 

    Es bastante simple, pero realmente ayuda a mejorar la calidad de la verificación, especialmente cuando desea verificar varias configuraciones de proxy.

    Asi que:

    • Compruebe si hay conectividad de red (haga que esto sea realmente bueno, tal vez incluso tenga registros enviados a los desarrolladores cuando haya falsos positivos para mejorar la función de NetworkIsAvailable)
    • Ping HTTP
    • (Haga un ciclo a través de configuraciones Proxy con HTTP Pings en cada uno)
     public static bool Isconnected = false; public static bool CheckForInternetConnection() { try { Ping myPing = new Ping(); String host = "google.com"; byte[] buffer = new byte[32]; int timeout = 1000; PingOptions pingOptions = new PingOptions(); PingReply reply = myPing.Send(host, timeout, buffer, pingOptions); if (reply.Status == IPStatus.Success) { return true; } else if (reply.Status == IPStatus.TimedOut) { return Isconnected; } else { return false; } } catch (Exception) { return false; } } public static void CheckConnection() { if (CheckForInternetConnection()) { Isconnected = true; } else { Isconnected = false; } } 
     bool bb = System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable(); if (bb == true) MessageBox.Show("Internet connections are available"); else MessageBox.Show("Internet connections are not available"); 

    Versión multi hilo de ping:

      using System; using System.Collections.Generic; using System.Diagnostics; using System.Net.NetworkInformation; using System.Threading; namespace OnlineCheck { class Program { static bool isOnline = false; static void Main(string[] args) { List ipList = new List { "1.1.1.1", // Bad ip "2.2.2.2", "4.2.2.2", "8.8.8.8", "9.9.9.9", "208.67.222.222", "139.130.4.5" }; int timeOut = 1000 * 5; // Seconds List threadList = new List(); foreach (string ip in ipList) { Thread threadTest = new Thread(() => IsOnline(ip)); threadList.Add(threadTest); threadTest.Start(); } Stopwatch stopwatch = Stopwatch.StartNew(); while (!isOnline && stopwatch.ElapsedMilliseconds < = timeOut) { Thread.Sleep(10); // Cooldown the CPU } foreach (Thread thread in threadList) { thread.Abort(); // We love threads, don't we? } Console.WriteLine("Am I online: " + isOnline.ToYesNo()); Console.ReadKey(); } static bool Ping(string host, int timeout = 3000, int buffer = 32) { bool result = false; try { Ping ping = new Ping(); byte[] byteBuffer = new byte[buffer]; PingOptions options = new PingOptions(); PingReply reply = ping.Send(host, timeout, byteBuffer, options); result = (reply.Status == IPStatus.Success); } catch (Exception ex) { } return result; } static void IsOnline(string host) { isOnline = Ping(host) || isOnline; } } public static class BooleanExtensions { public static string ToYesNo(this bool value) { return value ? "Yes" : "No"; } } } 

    Para mi aplicación, también probamos descargando un archivo pequeño.

     string remoteUri = "https://www.microsoft.com/favicon.ico" WebClient myWebClient = new WebClient(); try { byte[] myDataBuffer = myWebClient.DownloadData (remoteUri); if(myDataBuffer.length > 0) // Or add more validate. eg. checksum { return true; } } catch { return false; } 

    También. Algunos ISP pueden usar un servidor intermedio para almacenar en caché el archivo. Agregar un parámetro aleatorio no utilizado, por ej. https://www.microsoft.com/favicon.ico?req=random_number Puede evitar el almacenamiento en caché.

    Estoy teniendo problemas con esos métodos en mi enrutador / módem 3g, porque si se desconecta internet, el enrutador redirige la página a su página de respuesta, por lo que aún recibe un impulso y su código cree que hay internet. Las manzanas (u otras) tienen una página de definición de puntos calientes que siempre devuelve una respuesta determinada. La siguiente muestra devuelve la respuesta “Correcta”. ¡Así que estarás seguro de que podrías conectarte a Internet y obtener una respuesta real!

     public static bool CheckForInternetConnection() { try { using (var webClient = new WebClient()) using (var stream = webClient.OpenRead("http://captive.apple.com/hotspot-detect.html")) { if (stream != null) { //return true; stream.ReadTimeout = 1000; using (var reader = new StreamReader(stream, Encoding.UTF8, false)) { string line; while ((line = reader.ReadLine()) != null) { if (line == "SuccessSuccess") { return true; } Console.WriteLine(line); } } } return false; } } catch { } return false; } 

    Tengo tres pruebas para una conexión a Internet.

    • Referencia System.Net y System.Net.Sockets
    • Agregue las siguientes funciones de prueba:

    Prueba 1

     public bool IsOnlineTest1() { try { IPHostEntry dummy = Dns.GetHostEntry("https://www.google.com"); return true; } catch (SocketException ex) { return false; } } 

    Prueba 2

     public bool IsOnlineTest2() { try { IPHostEntry dummy = Dns.GetHostEntry("https://www.google.com"); return true; } catch (SocketException ex) { return false; } } 

    Prueba 3

     public bool IsOnlineTest3() { System.Net.WebRequest req = System.Net.WebRequest.Create("https://www.google.com"); System.Net.WebResponse resp = default(System.Net.WebResponse); try { resp = req.GetResponse(); resp.Close(); req = null; return true; } catch (Exception ex) { req = null; return false; } } 

    Realizando las pruebas

    Si CheckList un Dictionary of String y Boolean llamado CheckList , puede agregar los resultados de cada prueba a CheckList .

    Ahora, recurse a través de cada KeyValuePair usando un for...each ciclo.

    Si CheckList contiene un Value de true , entonces usted sabe que hay una conexión a Internet.

     public static bool HasConnection() { try { System.Net.IPHostEntry i = System.Net.Dns.GetHostEntry("www.google.com"); return true; } catch { return false; } } 

    Eso funciona