Qual è il modo più rapido ed efficiente per verificare la connettività Internet in .NET?
Windows NLM API
dovrebbe essere il migliore per questo. stackoverflow.com/questions/5405895/...
Qual è il modo più rapido ed efficiente per verificare la connettività Internet in .NET?
Windows NLM API
dovrebbe essere il migliore per questo. stackoverflow.com/questions/5405895/...
Risposte:
Qualcosa del genere dovrebbe funzionare.
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
in Cina ad esempio ...
Non è assolutamente possibile verificare in modo affidabile se esiste o meno una connessione a Internet (presumo si intenda l'accesso a Internet).
Puoi, tuttavia, richiedere risorse che non sono praticamente mai offline, come il ping di google.com o qualcosa di simile. Penso che questo sarebbe efficiente.
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
) funziona bene per me.
Beware - many schools and offices block the ping protocol.
se si utilizza questo metodo per un'applicazione che verrà utilizzata dai clienti, si sconsiglia questo metodo di controllo di internet
Invece di controllare, esegui semplicemente l'azione (richiesta web, posta, ftp, ecc.) E sii pronto affinché la richiesta fallisca, cosa che devi fare comunque, anche se il tuo controllo è andato a buon fine.
Considera quanto segue:
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
Se la rete non funziona, l'azione fallirà altrettanto rapidamente di un ping, ecc.
1 - start to perform action
2 - if the net is down(or goes down) the action will fail
NetworkInterface.GetIsNetworkAvailable
è molto inaffidabile. Basta avere un po 'di VMware o altra connessione LAN e restituirà un risultato errato. Anche sul Dns.GetHostEntry
metodo ero solo preoccupato se l'URL di test potesse essere bloccato nell'ambiente in cui la mia applicazione doveva essere distribuita.
Quindi un altro modo che ho scoperto è usare il InternetGetConnectedState
metodo. Il mio codice è
[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 per la connessione a Internet eseguendo il ping di Google:
new Ping().Send("www.google.com.mx").Status == IPStatus.Success
Non sono d'accordo con le persone che affermano: "Qual è il punto nel verificare la connettività prima di eseguire un'attività, come immediatamente dopo il controllo la connessione potrebbe andare persa". Sicuramente c'è un certo grado di incertezza in molti compiti di programmazione che noi sviluppatori intraprendiamo, ma ridurre l'incertezza a un livello di accettazione fa parte della sfida.
Di recente mi sono imbattuto in questo problema creando un'applicazione che includeva una funzionalità di mappatura collegata a un server di tessere online. Questa funzionalità doveva essere disabilitata quando si notava una mancanza di connettività Internet.
Alcune delle risposte in questa pagina sono state molto buone, ma hanno comunque causato molti problemi di prestazioni come l'impiccagione, principalmente in caso di assenza di connettività.
Ecco la soluzione che ho finito per usare, con l'aiuto di alcune di queste risposte e dei miei colleghi:
// 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
}));
}
}
Ho visto tutte le opzioni sopra elencate e l'unica opzione praticabile per verificare che Internet sia disponibile o meno è l'opzione "Ping". L'importazione [DllImport("Wininet.dll")]
e System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces()
qualsiasi altra variazione della NetworkInterface
classe non funziona correttamente nel rilevamento della disponibilità della rete. Questi metodi controllano solo se il cavo di rete è inserito o meno.
L '"opzione ping"
if
(La connessione è disponibile) ritorna true
if
(La connessione non è disponibile e il cavo di rete è inserito) ritorna false
if
(Il cavo di rete non è inserito) Throws an exception
L'interfaccia di rete
if
(Internet è disponibile) Restituisce True
if
(Internet non è disponibile e il cavo di rete è collegato) Restituisce True
if
(Il cavo di rete non è collegato) ritorna false
Il [DllImport ("Wininet.dll")]
if
(Internet è disponibile) Restituisce True
if
(Internet non è disponibile e il cavo di rete è collegato) Restituisce True
if
(Il cavo di rete non è collegato) ritorna false
Quindi, in caso di [DllImport("Wininet.dll")]
e NetworkInterface
Non c'è modo di sapere se è disponibile una connessione Internet.
Non risolve il problema della caduta della rete tra il controllo e l'esecuzione del codice ma è abbastanza affidabile
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;
}
Il ping google.com introduce una dipendenza dalla risoluzione DNS. Il ping 8.8.8.8 va bene, ma Google è a pochi passi da me. Tutto quello che devo fare è eseguire il ping della cosa più vicina a me che è su Internet.
Posso usare la funzione TTL di Ping per eseguire il ping dell'hop n. 1, quindi dell'hop n. 2, ecc., Finché non ricevo una risposta da qualcosa che si trova su un indirizzo instradabile; se quel nodo si trova su un indirizzo instradabile, allora è su Internet. Per la maggior parte di noi, hop # 1 sarà il nostro gateway / router locale e hop # 2 sarà il primo punto sull'altro lato della nostra connessione in fibra o altro.
Questo codice funziona per me e risponde più rapidamente di alcuni degli altri suggerimenti in questo thread perché sta eseguendo il ping di ciò che è più vicino a me su 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;
}
}
}
Ecco come viene implementato in Android.
Come prova di concetto, ho tradotto questo codice in 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;
}
}
Un'altra opzione è l'API Network List Manager che è disponibile per Vista e Windows 7. L'articolo MSDN qui . Nell'articolo è presente un collegamento per scaricare esempi di codice che consentono di eseguire questa operazione:
AppNetworkListUser nlmUser = new AppNetworkListUser();
Console.WriteLine("Is the machine connected to internet? " + nlmUser.NLM.IsConnectedToInternet.ToString());
Assicurarsi di aggiungere un riferimento alla libreria dei tipi di Elenco di rete 1.0 dalla scheda COM ... che verrà visualizzata come NETWORKLIST.
Cerca di evitare il test delle connessioni rilevando l'eccezione. perché ci aspettiamo davvero che a volte potremmo perdere la connessione di rete.
if (NetworkInterface.GetIsNetworkAvailable() &&
new Ping().Send(new IPAddress(new byte[] { 8, 8, 8, 8 }),2000).Status == IPStatus.Success)
//is online
else
//is offline
Se si desidera avvisare l'utente / agire ogni volta che si verifica una modifica della rete / connessione.
Usa API NLM:
Personalmente trovo la risposta migliore di Anton e Moffeltje , ma ho aggiunto un segno di spunta per escludere le reti virtuali create da VMWare e altri.
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
sarebbe ancora vero anche quando la rete non è connessa a Internet.
Versione multi thread del 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";
}
}
}
Non credo sia impossibile, ma non semplice.
Ho creato qualcosa del genere, e sì, non è perfetto, ma il primo passo è essenziale: verificare se c'è connettività di rete. L'API di Windows non fa un ottimo lavoro, quindi perché non fare un lavoro migliore?
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;
}
È piuttosto semplice, ma aiuta davvero a migliorare la qualità del controllo, soprattutto quando si desidera controllare varie configurazioni proxy.
Così:
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;
}
}
Utilizzare NetworkMonitor per monitorare lo stato della rete e la connessione Internet.
Campione:
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");
}
}
}
introduzione
In alcuni scenari è necessario verificare se Internet è disponibile o meno utilizzando il codice C # nelle applicazioni Windows. Può essere quello di scaricare o caricare un file utilizzando Internet in Windows Form o di ottenere alcuni dati dal database che si trova in una posizione remota, in queste situazioni il controllo di Internet è obbligatorio.
Ci sono alcuni modi per verificare la disponibilità di Internet usando C # dal codice dietro. Tutti questi modi sono spiegati qui, compresi i loro limiti.
L'API "wininet" può essere utilizzata per verificare se il sistema locale ha una connessione Internet attiva o meno. Lo spazio dei nomi utilizzato per questo è 'System.Runtime.InteropServices' e importa la dll 'wininet.dll' usando DllImport. Successivamente, crea una variabile booleana con extern static con un nome di funzione InternetGetConnectedState con due parametri descrizione e riservatoValue come mostrato nell'esempio.
Nota: il modificatore esterno viene utilizzato per dichiarare un metodo implementato esternamente. Un uso comune del modificatore extern è con l'attributo DllImport quando si utilizzano i servizi di interoperabilità per chiamare il codice non gestito. In questo caso, anche il metodo deve essere dichiarato statico.
Quindi creare un metodo con nome "IsInternetAvailable" come booleano. La funzione di cui sopra verrà utilizzata in questo metodo che restituisce lo stato Internet del sistema locale
[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'esempio seguente utilizza il metodo GetIsNetworkAvailable per determinare se è disponibile una connessione di rete.
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");
}
Note (secondo MSDN): una connessione di rete è considerata disponibile se un'interfaccia di rete è contrassegnata come "up" e non è un'interfaccia loopback o tunnel.
Ci sono molti casi in cui un dispositivo o un computer non è connesso a una rete utile ma è ancora considerato disponibile e GetIsNetworkAvailable restituirà true. Ad esempio, se il dispositivo che esegue l'applicazione è connesso a una rete wireless che richiede un proxy, ma il proxy non è impostato, GetIsNetworkAvailable restituirà true. Un altro esempio di quando GetIsNetworkAvailable restituirà true è se l'applicazione è in esecuzione su un computer collegato a un hub o router in cui l'hub o il router ha perso la connessione upstream.
Le classi Ping e PingReply consentono a un'applicazione di determinare se un computer remoto è accessibile in rete ottenendo risposta dall'host. Queste classi sono disponibili nello spazio dei nomi System.Net.NetworkInformation. L'esempio seguente mostra come eseguire il ping di 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;
}
Note (secondo MSDN): le applicazioni utilizzano la classe Ping per rilevare se è possibile raggiungere un computer remoto. La topologia di rete può determinare se Ping può contattare correttamente un host remoto. La presenza e la configurazione di proxy, apparecchiature NAT (Network Address Translation) o firewall possono impedire il successo del ping. Un ping riuscito indica solo che è possibile raggiungere l'host remoto sulla rete; la presenza di servizi di livello superiore (come un server Web) sull'host remoto non è garantita.
Commenti / Suggerimenti sono invitati. Buona programmazione ......!
Per la mia applicazione testiamo anche il download di piccoli file.
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;
}
Anche. Alcuni ISP possono utilizzare il server intermedio per memorizzare nella cache i file. Aggiungi un parametro casuale inutilizzato, ad es. https://www.microsoft.com/favicon.ico?req=random_number Può impedire la memorizzazione nella cache.
Sto riscontrando problemi con questo metodo sul mio router / modem 3g, perché se Internet è disconnesso il router reindirizza la pagina alla sua pagina di risposta, quindi ricevi ancora un vapore e il tuo codice pensa che ci sia Internet. Le mele (o altre) hanno una pagina di deduzione hot-spot che restituisce sempre una certa risposta. L'esempio seguente restituisce la risposta "Success". Quindi sarai esattamente sicuro di poter connettere Internet e ottenere una risposta reale!
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;
}
Ho tre test per una connessione a Internet.
System.Net
eSystem.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;
}
}
Esecuzione dei test
Se si effettua una Dictionary
di String
e Boolean
chiamato CheckList
, è possibile aggiungere i risultati di ogni test per CheckList
.
Ora, ripassa ciascuno di essi KeyValuePair
usando un for...each
ciclo.
Se CheckList
contiene un Value
di true
, allora sai che c'è una connessione a Internet.
public static bool HasConnection()
{
try
{
System.Net.IPHostEntry i = System.Net.Dns.GetHostEntry("www.google.com");
return true;
}
catch
{
return false;
}
}
Che funzioni