¿Cuál es la forma más rápida y eficiente de verificar la conectividad a Internet en .NET?
Windows NLM API
debería ser lo mejor para esto. stackoverflow.com/questions/5405895/…
¿Cuál es la forma más rápida y eficiente de verificar la conectividad a Internet en .NET?
Windows NLM API
debería ser lo mejor para esto. stackoverflow.com/questions/5405895/…
Respuestas:
Algo como esto debería funcionar.
public static bool CheckForInternetConnection()
{
try
{
using (var client = new WebClient())
using (client.OpenRead("http://google.com/generate_204"))
return true;
}
catch
{
return false;
}
}
I cannot image a world where www.google.com does not return some HTML
en China, por ejemplo ...
No hay absolutamente ninguna manera de que pueda verificar de manera confiable si hay una conexión a Internet o no (supongo que se refiere al 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;
}
8.8.8.8
o 8.8.4.4
) funciona bien para mí.
Beware - many schools and offices block the ping protocol.
si está utilizando este método para una aplicación que será utilizada por clientes, desaconsejaría este método de verificación de Internet
En lugar de verificar, simplemente realice la acción (solicitud web, correo, ftp, etc.) y esté preparado para que la solicitud falle, lo que debe hacer de todos modos, incluso si su verificación fue exitosa.
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 está inactiva, 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 tenga un poco de VMware u otra conexión LAN y obtendrá un resultado incorrecto. También sobre el Dns.GetHostEntry
método, me preocupaba si la URL de prueba podría estar bloqueada en el entorno donde se implementará mi aplicación.
Entonces, otra forma que descubrí es usando el InternetGetConnectedState
método. 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);
}
Una prueba de conexión a Internet haciendo ping a Google:
new Ping().Send("www.google.com.mx").Status == IPStatus.Success
No estoy de acuerdo con las personas que dicen: "¿Cuál es el punto de verificar la conectividad antes de realizar una tarea, ya que inmediatamente después de la verificación se puede perder la conexión". Seguramente hay un cierto grado de incertidumbre en muchas tareas de programación que nosotros, como desarrolladores, emprendemos, pero reducir la incertidumbre a un nivel de aceptación es parte del desafío.
Recientemente me encontré con este problema al crear una aplicación que incluye una función de mapeo que se vincula a un servidor de mosaico en línea. Esta funcionalidad se deshabilitaría cuando se observara una 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 el bloqueo, principalmente en el caso de la falta 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("<url of choice here>"));
}
}
}
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
}));
}
}
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 NetworkInterface
clase no funcionar bien en la detección de la disponibilidad de los métodos network.These solamente comprobar si el cable de red está conectado 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) vuelve false
if
(El cable de red no está enchufado) Throws an exception
La interfaz de red
if
(Internet está disponible) Devoluciones True
if
(Internet no está disponible y el cable de red está enchufado) Devoluciones True
if
(El cable de red no está enchufado) regresa false
El [DllImport ("Wininet.dll")]
if
(Internet está disponible) Devoluciones True
if
(Internet no está disponible y el cable de red está enchufado) Devoluciones True
if
(El cable de red no está enchufado) regresa false
Entonces, en caso de [DllImport("Wininet.dll")]
y NetworkInterface
no hay forma de saber si hay conexión a Internet disponible.
No resuelve el problema de la caída de la red entre la comprobación y la ejecución de su 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;
}
Hacer ping a google.com introduce una dependencia de resolución de DNS. Hacer ping 8.8.8.8 está bien, pero Google está a varios saltos 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 al salto n. ° 1, luego al salto n. ° 2, etc., hasta que reciba 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á nuestra puerta de enlace / enrutador local, y el salto n. ° 2 será el primer punto al 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 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
}
}
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;
}
}
Otra opción es la API de Network List Manager que está disponible para Vista y Windows 7. Artículo de MSDN aquí . En el artículo hay un enlace para descargar ejemplos 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 aparecerá como NETWORKLIST.
Intente evitar probar las conexiones detectando la excepción. porque realmente esperamos que a veces perdamos la conexión de red.
if (NetworkInterface.GetIsNetworkAvailable() &&
new Ping().Send(new IPAddress(new byte[] { 8, 8, 8, 8 }),2000).Status == IPStatus.Success)
//is online
else
//is offline
Si desea notificar al usuario / tomar medidas cada vez que ocurra un cambio en la red / conexión.
Utilice la API de NLM:
Personalmente encuentro la respuesta de Anton y moffeltje mejor, 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));
}
bool bb = System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable();
if (bb == true)
MessageBox.Show("Internet connections are available");
else
MessageBox.Show("Internet connections are not available");
bb
aún sería cierto incluso cuando la red no esté conectada a Internet.
Versión multiproceso 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<string> ipList = new List<string> {
"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<Thread> threadList = new List<Thread>();
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";
}
}
}
No creo que sea imposible, simplemente no es sencillo.
He construido algo como esto, y sí, no es perfecto, pero el primer paso es esencial: verificar si hay alguna 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.
Entonces:
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;
}
}
Use NetworkMonitor para monitorear el estado de la red y la conexión a Internet.
Muestra:
namespace AmRoNetworkMonitor.Demo
{
using System;
internal class Program
{
private static void Main()
{
NetworkMonitor.StateChanged += NetworkMonitor_StateChanged;
NetworkMonitor.StartMonitor();
Console.WriteLine("Press any key to stop monitoring.");
Console.ReadKey();
NetworkMonitor.StopMonitor();
Console.WriteLine("Press any key to close program.");
Console.ReadKey();
}
private static void NetworkMonitor_StateChanged(object sender, StateChangeEventArgs e)
{
Console.WriteLine(e.IsAvailable ? "Is Available" : "Is Not Available");
}
}
}
Introducción
En algunos escenarios, debe verificar si Internet está disponible o no utilizando el código C # en las aplicaciones de Windows. Puede ser para descargar o cargar un archivo a través de Internet en formularios de Windows o para obtener algunos datos de la base de datos que se encuentra en una ubicación remota, en estas situaciones, la verificación de Internet es obligatoria.
Hay algunas formas de verificar la disponibilidad de Internet usando C # desde el código detrás. Todas estas formas se explican aquí, incluidas sus limitaciones.
La API 'wininet' se puede usar para verificar si el sistema local tiene conexión a Internet activa o no. El espacio de nombres utilizado para esto es 'System.Runtime.InteropServices' e importa el dll 'wininet.dll' usando DllImport. Después de esto, cree una variable booleana con estática externa con un nombre de función InternetGetConnectedState con la descripción de dos parámetros y reservedValue como se muestra en el ejemplo.
Nota: El modificador externo se usa para declarar un método que se implementa externamente. Un uso común del modificador externo es con el atributo DllImport cuando usa los servicios de Interop para llamar a un código no administrado. En este caso, el método también debe declararse como estático.
A continuación, cree un método con el nombre 'IsInternetAvailable' como booleano. La función anterior se utilizará en este método que devuelve el estado de Internet del sistema local.
[DllImport("wininet.dll")]
private extern static bool InternetGetConnectedState(out int description, int reservedValue);
public static bool IsInternetAvailable()
{
try
{
int description;
return InternetGetConnectedState(out description, 0);
}
catch (Exception ex)
{
return false;
}
}
El siguiente ejemplo utiliza el método GetIsNetworkAvailable para determinar si hay una conexión de red disponible.
if (System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable())
{
System.Windows.MessageBox.Show("This computer is connected to the internet");
}
else
{
System.Windows.MessageBox.Show("This computer is not connected to the internet");
}
Observaciones (según MSDN): se considera que una conexión de red está disponible si alguna interfaz de red está marcada como "activada" y no es una interfaz de bucle o de túnel.
Hay muchos casos en los que un dispositivo o computadora no está conectado a una red útil, pero todavía se considera disponible y GetIsNetworkAvailable volverá verdadero. Por ejemplo, si el dispositivo que ejecuta la aplicación está conectado a una red inalámbrica que requiere un proxy, pero el proxy no está configurado, GetIsNetworkAvailable devolverá true. Otro ejemplo de cuándo GetIsNetworkAvailable devolverá verdadero es si la aplicación se está ejecutando en una computadora que está conectada a un concentrador o enrutador donde el concentrador o enrutador ha perdido la conexión ascendente.
Las clases Ping y PingReply permiten que una aplicación determine si se puede acceder a una computadora remota a través de la red mediante la respuesta del host. Estas clases están disponibles en el espacio de nombres System.Net.NetworkInformation. El siguiente ejemplo muestra cómo hacer ping a un host.
protected bool CheckConnectivity(string ipAddress)
{
bool connectionExists = false;
try
{
System.Net.NetworkInformation.Ping pingSender = new System.Net.NetworkInformation.Ping();
System.Net.NetworkInformation.PingOptions options = new System.Net.NetworkInformation.PingOptions();
options.DontFragment = true;
if (!string.IsNullOrEmpty(ipAddress))
{
System.Net.NetworkInformation.PingReply reply = pingSender.Send(ipAddress);
connectionExists = reply.Status ==
System.Net.NetworkInformation.IPStatus.Success ? true : false;
}
}
catch (PingException ex)
{
Logger.LogException(ex.Message, ex);
}
return connectionExists;
}
Observaciones (según MSDN): las aplicaciones utilizan la clase Ping para detectar si se puede acceder a una computadora remota. La topología de la red puede determinar si Ping puede contactar con éxito a un host remoto. La presencia y configuración de servidores proxy, equipos de traducción de direcciones de red (NAT) o firewalls pueden evitar que Ping tenga éxito. Un Ping exitoso indica solo que se puede llegar al host remoto en la red; no se garantiza la presencia de servicios de nivel superior (como un servidor web) en el host remoto.
Comentarios / Sugerencias están invitados. Feliz codificación ......!
Para mi aplicación también probamos descargando un pequeño archivo.
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. Añadir parámetro aleatorio no utilizado, por ejemplo. https://www.microsoft.com/favicon.ico?req=random_number Puede evitar el almacenamiento en caché.
Tengo un problema con ese método en mi enrutador / módem 3g, porque si Internet está desconectado, el enrutador redirige la página a su página de respuesta, por lo que aún obtiene un vapor y su código cree que hay internet. Las manzanas (u otras) tienen una página de detección de puntos críticos que siempre devuelve una respuesta determinada. La siguiente muestra devuelve la respuesta "Éxito". ¡Entonces estará exactamente seguro de que puede conectarse 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 == "<HTML><HEAD><TITLE>Success</TITLE></HEAD><BODY>Success</BODY></HTML>")
{
return true;
}
Console.WriteLine(line);
}
}
}
return false;
}
}
catch
{
}
return false;
}
Tengo tres pruebas para una conexión a Internet.
System.Net
ySystem.Net.Sockets
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 realiza un Dictionary
de String
y Boolean
llamó CheckList
, puede agregar los resultados de cada prueba CheckList
.
Ahora, repita a través de cada uno KeyValuePair
usando un for...each
bucle.
Si CheckList
contiene un Value
de true
, entonces 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