Quel est le moyen le plus rapide et le plus efficace de vérifier la connectivité Internet dans .NET?
Quelque chose comme ça devrait marcher.
public static bool CheckForInternetConnection()
{
try
{
using (var client = new WebClient())
using (client.OpenRead("http://clients3.google.com/generate_204"))
{
return true;
}
}
catch
{
return false;
}
}
Il n’ya absolument aucun moyen de vérifier de manière fiable s’il existe ou non une connexion Internet (je suppose que vous voulez dire par accès à Internet).
Vous pouvez toutefois demander des ressources qui ne sont pratiquement jamais hors ligne, telles que la commande ping de google.com ou quelque chose de similaire. Je pense que cela 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;
}
Au lieu de vérifier, effectuez simplement l'action (requête Web, mail, 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 abouti.
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. Avoir juste une connexion VMware ou une autre connexion LAN et le résultat sera erroné . Egalement à propos de la méthode Dns.GetHostEntry
Je voulais simplement savoir si l'URL de test pourrait être bloquée dans l'environnement où mon application va être déployée.
J'ai donc découvert une autre méthode en utilisant la méthode InternetGetConnectedState
. 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);
}
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'exécuter une tâche, car immédiatement après la vérification, la connexion peut être perdue" ... entreprendre, mais réduire l’incertitude à un niveau d’acceptation fait partie du défi.
J'ai récemment rencontré ce problème en créant une application comportant une fonctionnalité de mappage liée à un serveur de tuiles en ligne. Cette fonctionnalité devait être désactivée lorsqu'un manque de connectivité Internet était constaté.
Certaines des réponses fournies sur cette page étaient très bonnes, mais ont néanmoins posé de nombreux problèmes de performances, tels que le blocage, principalement dans le cas de l'absence de connectivité.
Voici la solution que j'ai finalement utilisée, à 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
}));
}
}
Un test de connexion Internet en envoyant une requête ping à Google:
new Ping().Send("www.google.com.mx").Status == IPStatus.Success
Ne résout pas le problème de la coupure du 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;
}
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" . Importer [DllImport("Wininet.dll")]
et System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces()
Ou toute autre variante de la classe NetworkInterface
ne fonctionne pas bien pour détecter la disponibilité du réseau. Ces méthodes vérifient uniquement si le câble de réseau est branché ou non.
L'option "Ping"
if
(La connexion est disponible) renvoie 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) Renvoie True
if
(Internet n'est pas disponible et le câble réseau est branché) Retourne True
if
(le câble réseau n'est pas branché) renvoie false
Le [DllImport ("Wininet.dll")]
if
(Internet est disponible) Renvoie True
if
(Internet n'est pas disponible et le câble réseau est branché) Retourne True
if
(le câble réseau n'est pas branché) renvoie false
Donc, en cas de [DllImport("Wininet.dll")]
et NetworkInterface
, il n’ya aucun moyen de savoir si une connexion 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;
}
}
Voici comment cela est mis en œuvre dans Android.
Pour prouver le 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
}
}
Le ping sur google.com introduit une dépendance à la résolution DNS. Pinging 8.8.8.8, c'est bien, mais Google est à quelques sauts de distance de moi. Tout ce que je dois faire est de faire un ping sur la chose la plus proche de moi qui est sur Internet.
Je peux utiliser la fonction TTL de Ping pour exécuter les étapes 1, puis 2, etc. si ce nœud est 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;
}
}
}
Je trouve personnellement la réponse de Anton et moffeltje best, mais j’ai ajouté une coche pour exclure les réseaux virtuels configurés 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));
}
Une autre option est l’API Network List Manager, disponible pour Vista et Windows 7. Article MSDN ici . Dans cet article, vous trouverez un lien pour télécharger des exemples de code vous permettant de le faire:
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 Network List 1.0 à partir de l’onglet COM ... qui apparaîtra sous la forme NETWORKLIST.
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");
}
}
}
Essaye ça:
using System.Net.NetworkInformation;
bool isNetAvailable = NetworkInterface.GetIsNetworkAvailable();
bool bb = System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable();
if (bb == true)
MessageBox.Show("Internet connections are available");
else
MessageBox.Show("Internet connections are not available");
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;
}
}
Si vous souhaitez informer l'utilisateur/prendre des mesures chaque fois qu'un changement de réseau/connexion se produit.
Utiliser l'API NLM:
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 penserais 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 existe une connectivité réseau. Windows Api ne fait pas du bon 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é du contrôle, en particulier lorsque vous souhaitez vérifier différentes configurations de proxy.
Alors: