Qual é a maneira mais rápida e eficiente de verificar a conectividade da Internet no .NET?
Windows NLM API
deve ser o melhor para isso. stackoverflow.com/questions/5405895/…
Qual é a maneira mais rápida e eficiente de verificar a conectividade da Internet no .NET?
Windows NLM API
deve ser o melhor para isso. stackoverflow.com/questions/5405895/…
Respostas:
Algo assim deve 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
na China, por exemplo ...
Não há absolutamente nenhuma maneira que você pode confiavelmente verificar com se há ou não uma conexão à Internet (suponho que você queira dizer acesso à internet).
No entanto, você pode solicitar recursos que nunca estão offline, como pingar google.com ou algo semelhante. Eu acho que isso seria 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
ou 8.8.4.4
) funciona bem para mim.
Beware - many schools and offices block the ping protocol.
se você estiver usando este método para um aplicativo que será usado por clientes gostaria de aconselhar contra este método de verificação internet
Em vez de verificar, basta executar a ação (solicitação da web, email, ftp etc.) e estar preparado para a solicitação falhar, o que você deve fazer de qualquer maneira, mesmo que sua verificação tenha sido bem-sucedida.
Considere o seguinte:
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 a rede estiver inativa, sua ação falhará tão rapidamente quanto um ping, etc.
1 - start to perform action
2 - if the net is down(or goes down) the action will fail
NetworkInterface.GetIsNetworkAvailable
é muito confiável. Basta ter alguma conexão VMware ou outra LAN e ele retornará um resultado errado. Também sobre o Dns.GetHostEntry
método, eu estava preocupado apenas com o fato de o URL de teste estar bloqueado no ambiente em que meu aplicativo será implantado.
Então, outra maneira que eu descobri é usando o InternetGetConnectedState
método Meu código é
[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);
}
Um teste para conexão à Internet executando ping no Google:
new Ping().Send("www.google.com.mx").Status == IPStatus.Success
Discordo das pessoas que afirmam: "Qual é o sentido de verificar a conectividade antes de executar uma tarefa, pois imediatamente após a verificação, a conexão pode ser perdida". Certamente, há um certo grau de incerteza em muitas tarefas de programação que nós, como desenvolvedores, realizamos, mas reduzir a incerteza a um nível de aceitação faz parte do desafio.
Recentemente, me deparei com esse problema ao criar um aplicativo que inclui um recurso de mapeamento vinculado a um servidor de blocos on-line. Essa funcionalidade era para ser desativada quando uma falta de conectividade com a Internet era observada.
Algumas das respostas nesta página foram muito boas, mas causaram muitos problemas de desempenho, como interrupções, principalmente no caso de ausência de conectividade.
Aqui está a solução que acabei usando, com a ajuda de algumas dessas respostas e de meus 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
}));
}
}
Eu vi todas as opções listadas acima e a única opção viável para verificar se a Internet está disponível ou não é a opção "Ping". A importação [DllImport("Wininet.dll")]
e / System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces()
ou qualquer outra variação da NetworkInterface
classe não funciona bem na detecção da disponibilidade da rede. Esses métodos só verificam se o cabo de rede está conectado ou não.
A "opção Ping"
if
(Conexão disponível) retorna true
if
(A conexão não está disponível e o cabo de rede está conectado) retorna false
if
(O cabo de rede não está conectado) Throws an exception
O NetworkInterface
if
(Internet está disponível) True
if
(A Internet não está disponível e o cabo de rede está conectado) True
if
(O cabo de rede não está conectado) retorna false
O [DllImport ("Wininet.dll")]
if
(Internet está disponível) True
if
(A Internet não está disponível e o cabo de rede está conectado) True
if
(O cabo de rede não está conectado) retorna false
Portanto, no caso de [DllImport("Wininet.dll")]
e NetworkInterface
Não há como saber se a conexão à Internet está disponível.
Não resolve o problema de queda de rede entre verificar e executar seu código, mas é razoavelmente confiável
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;
}
O ping do google.com introduz uma dependência de resolução de DNS. O ping 8.8.8.8 está bom, mas o Google está a vários passos de mim. Tudo o que preciso fazer é executar ping na coisa mais próxima de mim que está na internet.
Eu posso usar o recurso TTL do Ping para executar o ping no salto 1, depois o salto 2, etc., até obter uma resposta de algo que esteja em um endereço roteável; se esse nó estiver em um endereço roteável, estará na internet. Para a maioria de nós, o salto número 1 será nosso gateway / roteador local e o salto número 2 será o primeiro ponto do outro lado da nossa conexão de fibra óptica ou qualquer outra coisa.
Esse código funciona para mim e responde mais rapidamente do que algumas das outras sugestões deste segmento, porque está executando o ping do que estiver mais próximo de mim na 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;
}
}
}
Veja como isso é implementado no Android.
Como prova de conceito, traduzi esse código para 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;
}
}
Outra opção é a API do Network List Manager, disponível para o Vista e Windows 7. Artigo MSDN aqui . No artigo, há um link para baixar exemplos de códigos que permitem fazer isso:
AppNetworkListUser nlmUser = new AppNetworkListUser();
Console.WriteLine("Is the machine connected to internet? " + nlmUser.NLM.IsConnectedToInternet.ToString());
Certifique-se de adicionar uma referência à Biblioteca de tipos da lista de rede 1.0 na guia COM ... que será exibida como NETWORKLIST.
Tente evitar o teste de conexões capturando a exceção. porque realmente esperamos que, às vezes, possamos perder a conexão de rede.
if (NetworkInterface.GetIsNetworkAvailable() &&
new Ping().Send(new IPAddress(new byte[] { 8, 8, 8, 8 }),2000).Status == IPStatus.Success)
//is online
else
//is offline
Se você deseja notificar o usuário / executar uma ação sempre que ocorrer uma alteração na rede / conexão.
Use a API NLM:
Pessoalmente, acho melhor a resposta de Anton e moffeltje , mas adicionei uma verificação para excluir redes virtuais configuradas pelo VMWare e outros.
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
ainda seria verdade mesmo quando a rede não estiver conectada à Internet.
Versão multiencadeada do 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";
}
}
}
Eu não acho que é impossível, apenas não é direto.
Eu criei algo assim, e sim, não é perfeito, mas o primeiro passo é essencial: verificar se há alguma conectividade de rede. A API do Windows não faz um ótimo trabalho, então por que não fazer um trabalho melhor?
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;
}
É bem simples, mas realmente ajuda a melhorar a qualidade da verificação, especialmente quando você deseja verificar várias configurações de proxy.
Assim:
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 o NetworkMonitor para monitorar o estado da rede e a conexão à Internet.
Amostra:
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");
}
}
}
Introdução
Em alguns cenários, é necessário verificar se a Internet está disponível ou não usando o código C # nos aplicativos Windows. Pode ser fazer o download ou upload de um arquivo usando a Internet no Windows Forms ou obter alguns dados do banco de dados que está em local remoto, nessas situações, a verificação da Internet é obrigatória.
Existem algumas maneiras de verificar a disponibilidade da Internet usando C # do código atrás. Todas essas formas são explicadas aqui, incluindo suas limitações.
A API 'wininet' pode ser usada para verificar se o sistema local tem conexão ativa com a Internet ou não. O espaço para nome usado para isso é 'System.Runtime.InteropServices' e importa a dll 'wininet.dll' usando DllImport. Depois disso, crie uma variável booleana com estática externa com um nome de função InternetGetConnectedState com a descrição de dois parâmetros e o valor reservado, conforme mostrado no exemplo.
Nota: O modificador externo é usado para declarar um método implementado externamente. Um uso comum do modificador externo é com o atributo DllImport quando você está usando os serviços de interoperabilidade para chamar código não gerenciado. Nesse caso, o método também deve ser declarado como estático.
Em seguida, crie um método com o nome 'IsInternetAvailable' como booleano. A função acima será usada neste método que retorna o status da Internet do 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;
}
}
O exemplo a seguir usa o método GetIsNetworkAvailable para determinar se uma conexão de rede está disponível.
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");
}
Comentários (Conforme MSDN): Uma conexão de rede é considerada disponível se qualquer interface de rede estiver marcada como "ativa" e não for uma interface de loopback ou túnel.
Existem muitos casos em que um dispositivo ou computador não está conectado a uma rede útil, mas ainda é considerado disponível e GetIsNetworkAvailable retornará true. Por exemplo, se o dispositivo que está executando o aplicativo estiver conectado a uma rede sem fio que requer um proxy, mas o proxy não estiver definido, GetIsNetworkAvailable retornará true. Outro exemplo de quando GetIsNetworkAvailable retornará true é se o aplicativo estiver sendo executado em um computador conectado a um hub ou roteador em que o hub ou roteador perdeu a conexão upstream.
As classes Ping e PingReply permitem que um aplicativo determine se um computador remoto está acessível pela rede, obtendo resposta do host. Essas classes estão disponíveis no espaço para nome System.Net.NetworkInformation. O exemplo a seguir mostra como executar ping em um 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;
}
Comentários (Conforme o MSDN): Os aplicativos usam a classe Ping para detectar se um computador remoto está acessível. A topologia de rede pode determinar se o Ping pode entrar em contato com êxito com um host remoto. A presença e configuração de proxies, equipamentos de conversão de endereços de rede (NAT) ou firewalls podem impedir o êxito do ping. Um ping bem-sucedido indica apenas que o host remoto pode ser acessado na rede; a presença de serviços de nível superior (como um servidor da Web) no host remoto não é garantida.
Comentários / sugestões são convidados. Feliz codificação ......!
Para minha aplicação, também testamos o download de um arquivo minúsculo.
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;
}
Além disso. Alguns ISP podem usar o servidor intermediário para armazenar em cache o arquivo. Adicione um parâmetro aleatório não utilizado, por exemplo. https://www.microsoft.com/favicon.ico?req=random_number Pode impedir o cache.
Estou tendo problemas com esse método no meu roteador / modem 3G, porque se a Internet for desconectada, o roteador redireciona a página para sua página de resposta, para que você ainda receba um vapor e seu código pense que existe internet. Maçãs (ou outras) têm uma página de dedução de hot spot que sempre retorna uma certa resposta. O exemplo a seguir retorna a resposta "Sucesso". Assim, você terá exatamente certeza de que poderá conectar a Internet e obter uma resposta 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;
}
Eu tenho três testes para uma conexão com a Internet.
System.Net
eSystem.Net.Sockets
Teste 1
public bool IsOnlineTest1()
{
try
{
IPHostEntry dummy = Dns.GetHostEntry("https://www.google.com");
return true;
}
catch (SocketException ex)
{
return false;
}
}
Teste 2
public bool IsOnlineTest2()
{
try
{
IPHostEntry dummy = Dns.GetHostEntry("https://www.google.com");
return true;
}
catch (SocketException ex)
{
return false;
}
}
Teste 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;
}
}
Executando os testes
Se você fizer um Dictionary
de String
e Boolean
chamar CheckList
, poderá adicionar os resultados de cada teste aoCheckList
.
Agora, recorra a cada KeyValuePair
um usando umfor...each
loop.
Se CheckList
contiver um Value
de true
, você saberá que há uma conexão com a Internet.
public static bool HasConnection()
{
try
{
System.Net.IPHostEntry i = System.Net.Dns.GetHostEntry("www.google.com");
return true;
}
catch
{
return false;
}
}
Isso funciona