Quel est le moyen le plus rapide et le plus efficace de vérifier la connectivité Internet dans .NET?
Windows NLM API
devrait être le meilleur pour cela. stackoverflow.com/questions/5405895/…
Quel est le moyen le plus rapide et le plus efficace de vérifier la connectivité Internet dans .NET?
Windows NLM API
devrait être le meilleur pour cela. stackoverflow.com/questions/5405895/…
Réponses:
Quelque chose comme ça devrait fonctionner.
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 Chine par exemple ...
Il n'y a absolument aucun moyen de vérifier de manière fiable s'il y a une connexion Internet ou non (je suppose que vous voulez dire l'accès à Internet).
Vous pouvez cependant demander des ressources qui ne sont pratiquement jamais hors ligne, comme envoyer un ping à google.com ou quelque chose de similaire. Je pense que ce serait efficace.
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
ou 8.8.4.4
) fonctionne bien pour moi.
Beware - many schools and offices block the ping protocol.
si vous utilisez cette méthode pour une application qui sera utilisée par les clients, je déconseille cette méthode de vérification d'Internet
Au lieu de vérifier, effectuez simplement l'action (demande Web, courrier, ftp, etc.) et préparez-vous à l'échec de la demande, ce que vous devez faire de toute façon, même si votre vérification a réussi.
Considérer ce qui suit:
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 le réseau est en panne, votre action échouera aussi rapidement qu'un ping, etc.
1 - start to perform action
2 - if the net is down(or goes down) the action will fail
NetworkInterface.GetIsNetworkAvailable
est très peu fiable. Ayez juste une connexion VMware ou autre LAN et cela retournera un mauvais résultat. Aussi à propos de la Dns.GetHostEntry
méthode, je voulais juste savoir si l'URL de test pouvait être bloquée dans l'environnement où mon application allait se déployer.
Donc, une autre façon dont j'ai découvert est d'utiliser la InternetGetConnectedState
méthode. Mon code est
[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);
}
Un test de connexion Internet en envoyant une requête ping à Google:
new Ping().Send("www.google.com.mx").Status == IPStatus.Success
Je ne suis pas d'accord avec les personnes qui déclarent: "Quel est l'intérêt de vérifier la connectivité avant d'effectuer une tâche, car immédiatement après le contrôle, la connexion peut être perdue". Certes, il existe un certain degré d'incertitude dans de nombreuses tâches de programmation que nous, en tant que développeurs, entreprenons, mais réduire l'incertitude à un niveau d'acceptation fait partie du défi.
J'ai récemment rencontré ce problème lors de la création d'une application incluant une fonction de mappage reliée à un serveur de tuiles en ligne. Cette fonctionnalité devait être désactivée en cas de manque de connectivité Internet.
Certaines des réponses sur cette page étaient très bonnes, mais ont cependant causé beaucoup de problèmes de performances tels que le blocage, principalement en cas d'absence de connectivité.
Voici la solution que j'ai fini par utiliser, avec l'aide de certaines de ces réponses et de mes collègues:
// 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
}));
}
}
J'ai vu toutes les options énumérées ci-dessus et la seule option viable pour vérifier si Internet est disponible ou non est l'option "Ping". L'importation [DllImport("Wininet.dll")]
et System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces()
ou toute autre variation de la NetworkInterface
classe ne fonctionne pas bien pour détecter la disponibilité du réseau. Ces méthodes vérifient uniquement si le câble réseau est branché ou non.
L'option "Ping"
if
(La connexion est disponible) retourne true
if
(La connexion n'est pas disponible et le câble réseau est branché) renvoie false
if
(Le câble réseau n'est pas branché) Throws an exception
L'interface réseau
if
(Internet est disponible) Retours True
if
(Internet n'est pas disponible et le câble réseau est branché) True
if
(Le câble réseau n'est pas branché) renvoie false
Le [DllImport ("Wininet.dll")]
if
(Internet est disponible) Retours True
if
(Internet n'est pas disponible et le câble réseau est branché) True
if
(Le câble réseau n'est pas branché) renvoie false
Donc, en cas de [DllImport("Wininet.dll")]
et NetworkInterface
Il n'y a aucun moyen de savoir si une connexion Internet est disponible.
Ne résout pas le problème de panne de réseau entre la vérification et l'exécution de votre code mais est assez fiable
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;
}
Pinging google.com introduit une dépendance de résolution DNS. Pinging 8.8.8.8 est très bien, mais Google est à plusieurs sauts de moi. Tout ce que je dois faire est de cingler la chose la plus proche de moi qui est sur Internet.
Je peux utiliser la fonction TTL de Ping pour envoyer un ping au hop # 1, puis au hop # 2, etc., jusqu'à ce que j'obtienne une réponse de quelque chose qui se trouve sur une adresse routable; si ce nœud se trouve sur une adresse routable, il est sur Internet. Pour la plupart d'entre nous, le saut n ° 1 sera notre passerelle / routeur local et le saut n ° 2 sera le premier point de l'autre côté de notre connexion fibre ou autre.
Ce code fonctionne pour moi et répond plus rapidement que certaines des autres suggestions de ce fil, car il envoie une requête ping à ce qui est le plus proche de moi sur 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;
}
}
}
Voici comment il est implémenté dans Android.
Comme preuve de concept, j'ai traduit ce code en 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;
}
}
Une autre option est l'API Network List Manager qui est disponible pour Vista et Windows 7. Article MSDN ici . Dans l'article se trouve un lien pour télécharger des exemples de code qui vous permettent de faire ceci:
AppNetworkListUser nlmUser = new AppNetworkListUser();
Console.WriteLine("Is the machine connected to internet? " + nlmUser.NLM.IsConnectedToInternet.ToString());
Assurez-vous d'ajouter une référence à la bibliothèque de types de la liste de réseaux 1.0 dans l'onglet COM ... qui apparaîtra comme NETWORKLIST.
Essayez d'éviter de tester les connexions en interceptant l'exception. car nous nous attendons vraiment à ce que parfois nous perdions la connexion réseau.
if (NetworkInterface.GetIsNetworkAvailable() &&
new Ping().Send(new IPAddress(new byte[] { 8, 8, 8, 8 }),2000).Status == IPStatus.Success)
//is online
else
//is offline
Si vous souhaitez informer l'utilisateur / prendre des mesures chaque fois qu'un changement de réseau / connexion se produit.
Utilisez l'API NLM:
Personnellement , je trouve le mieux la réponse d' Anton et de moffeltje , mais j'ai ajouté une vérification pour exclure les réseaux virtuels mis en place par VMWare et d'autres.
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
serait toujours vrai même lorsque le réseau n'est pas connecté à Internet.
Version multi-thread 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";
}
}
}
Je ne pense pas que ce soit impossible, mais pas simple.
J'ai construit quelque chose comme ça, et oui ce n'est pas parfait, mais la première étape est essentielle: vérifier s'il y a une connectivité réseau. L'API Windows ne fait pas un excellent travail, alors pourquoi ne pas faire un meilleur travail?
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;
}
C'est assez simple, mais cela aide vraiment à améliorer la qualité de la vérification, surtout lorsque vous souhaitez vérifier diverses configurations de proxy.
Alors:
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;
}
}
Utilisez NetworkMonitor pour surveiller l'état du réseau et la connexion Internet.
Échantillon:
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");
}
}
}
introduction
Dans certains scénarios, vous devez vérifier si Internet est disponible ou non en utilisant le code C # dans les applications Windows. Il peut s'agir de télécharger ou de télécharger un fichier via Internet sous Windows ou d'obtenir des données d'une base de données distante, dans ces situations, la vérification d'Internet est obligatoire.
Il existe plusieurs façons de vérifier la disponibilité d'Internet en utilisant C # à partir du code derrière. Toutes ces méthodes sont expliquées ici, y compris leurs limites.
L'API 'wininet' peut être utilisée pour vérifier si le système local a une connexion Internet active ou non. L'espace de noms utilisé pour cela est «System.Runtime.InteropServices» et importez la dll «wininet.dll» à l'aide de DllImport. Après cela, créez une variable booléenne avec statique externe avec un nom de fonction InternetGetConnectedState avec une description de deux paramètres et réservéValue comme indiqué dans l'exemple.
Remarque: Le modificateur extern est utilisé pour déclarer une méthode implémentée en externe. Une utilisation courante du modificateur extern est avec l'attribut DllImport lorsque vous utilisez des services Interop pour appeler du code non managé. Dans ce cas, la méthode doit également être déclarée comme statique.
Créez ensuite une méthode avec le nom 'IsInternetAvailable' comme booléen. La fonction ci-dessus sera utilisée dans cette méthode qui renvoie le statut Internet du système 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;
}
}
L'exemple suivant utilise la méthode GetIsNetworkAvailable pour déterminer si une connexion réseau est 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");
}
Remarques (selon MSDN): Une connexion réseau est considérée comme disponible si une interface réseau est marquée "up" et n'est pas une interface de bouclage ou de tunnel.
Il existe de nombreux cas dans lesquels un périphérique ou un ordinateur n'est pas connecté à un réseau utile mais est toujours considéré comme disponible et GetIsNetworkAvailable renvoie true. Par exemple, si le périphérique exécutant l'application est connecté à un réseau sans fil qui nécessite un proxy, mais que le proxy n'est pas défini, GetIsNetworkAvailable renvoie true. Un autre exemple de moment où GetIsNetworkAvailable retournera true est si l'application s'exécute sur un ordinateur connecté à un concentrateur ou un routeur où le concentrateur ou le routeur a perdu la connexion en amont.
Les classes Ping et PingR répondre permettent à une application de déterminer si un ordinateur distant est accessible sur le réseau en obtenant une réponse de l'hôte. Ces classes sont disponibles dans l'espace de noms System.Net.NetworkInformation. L'exemple suivant montre comment envoyer une requête ping à un hôte.
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;
}
Remarques (selon MSDN): les applications utilisent la classe Ping pour détecter si un ordinateur distant est accessible. La topologie du réseau peut déterminer si Ping peut contacter avec succès un hôte distant. La présence et la configuration de proxys, d'équipements de traduction d'adresses réseau (NAT) ou de pare-feu peuvent empêcher Ping de réussir. Un ping réussi indique uniquement que l'hôte distant peut être atteint sur le réseau; la présence de services de niveau supérieur (comme un serveur Web) sur l'hôte distant n'est pas garantie.
Les commentaires / suggestions sont invités. Bon codage ......!
Pour mon application, nous testons également en téléchargeant un petit fichier.
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;
}
Aussi. Certains FAI peuvent utiliser un serveur intermédiaire pour mettre en cache le fichier. Ajouter un paramètre aléatoire inutilisé, par exemple. https://www.microsoft.com/favicon.ico?req=random_number Peut empêcher la mise en cache.
J'ai un problème avec cette méthode sur mon routeur / modem 3G, car si Internet est déconnecté, le routeur redirige la page vers sa page de réponse, donc vous obtenez toujours une vapeur et votre code pense qu'il y a Internet. Les pommes (ou autres) ont une page de détection de points chauds qui renvoie toujours une certaine réponse. L'exemple suivant renvoie la réponse «Succès». Vous serez donc exactement sûr de pouvoir vous connecter à Internet et obtenir une réponse réelle!
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;
}
J'ai trois tests pour une connexion Internet.
System.Net
etSystem.Net.Sockets
Test 1
public bool IsOnlineTest1()
{
try
{
IPHostEntry dummy = Dns.GetHostEntry("https://www.google.com");
return true;
}
catch (SocketException ex)
{
return false;
}
}
Test 2
public bool IsOnlineTest2()
{
try
{
IPHostEntry dummy = Dns.GetHostEntry("https://www.google.com");
return true;
}
catch (SocketException ex)
{
return false;
}
}
Test 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;
}
}
Réalisation des tests
Si vous faites un Dictionary
de String
et Boolean
appelé CheckList
, vous pouvez ajouter les résultats de chaque test CheckList
.
Maintenant, récapitulez à travers chacun en KeyValuePair
utilisant une for...each
boucle.
Si CheckList
contient un Value
de true
, alors vous savez qu'il existe une connexion Internet.
public static bool HasConnection()
{
try
{
System.Net.IPHostEntry i = System.Net.Dns.GetHostEntry("www.google.com");
return true;
}
catch
{
return false;
}
}
Ça marche