Каков наилучший способ проверить подключение к Интернету с помощью .NET?

237

Какой самый быстрый и эффективный способ проверить подключение к Интернету в .NET?

Мохит Дешпанде
источник
6
Если у пользователя есть интернет-соединение. Если пользователь может подключиться к Интернету. Для того, чтобы отправить письмо по электронной почте.
Мохит Дешпанде
11
Просто отправьте электронное письмо. Если пользователь не подключен, вы, скорее всего, получите какое-то исключение (которое вам, вероятно, придется в любом случае обработать).
Сет
15
Кроме того , обратите внимание , что нет никакого способа , чтобы проверить , если пользователь будет подключен к Интернету; все, что вы можете сказать, если они были связаны в прошлом . Предположим, у вас есть метод: «bool c = IsConnected (); if (c) {DoSomething ();}» - между вызовом IsConnected и DoSomething маршрутизатор беспроводной сети мог быть отключен. IsConnected действительно должен называться WasRecentlyConnected.
Эрик Липперт
Windows NLM APIдолжен быть лучшим для этого. stackoverflow.com/questions/5405895/…
Махбубур Рахман

Ответы:

292

Нечто подобное должно работать.

System.Net.WebClient

public static bool CheckForInternetConnection()
{
    try
    {
        using (var client = new WebClient())
            using (client.OpenRead("http://google.com/generate_204")) 
                return true; 
    }
    catch
    {
        return false;
    }
}
ChaosPandion
источник
18
Это, вероятно, лучше, чем пинг Google, потому что я думаю, что у нас нет гарантии, что Google продолжает отвечать на пинги. С другой стороны, я не могу представить себе мир, в котором www.google.com не возвращает HTML :)
Даниэль Вассалло,
3
@Daniel: правда с одной стороны, но с другой стороны, на самом деле загрузка сайта - это немного накладные расходы
Лев
9
В любом случае, нет причин возвращать 4KB - просто используйте client.OpenRead (url). Если он не выбрасывает исключение, он может подключиться.
Джош М.
14
Это на самом деле не так эффективно. Используя это, моя программа запускается через 1 минуту, если нет интернета. Вероятно, из-за попытки разрешить DNS. Пинг 8.8.8.8 (гугл днс) изменил его на 3 секунды.
MadBoy
8
@DanielVassallo I cannot image a world where www.google.com does not return some HTMLв Китае, например ...
Жером Мевель
84

Нет абсолютно никакого способа надежно проверить, есть ли подключение к Интернету или нет (я предполагаю, что вы имеете в виду доступ к Интернету).

Однако вы можете запросить ресурсы, которые практически никогда не отключены, например, pinging google.com или что-то подобное. Я думаю, что это будет эффективно.

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;
}
Лео
источник
24
+1 «Совершенно невозможно проверить, есть ли подключение к интернету»
woz
6
Все, что это делает, это проверяет, что Google включен, когда вы проверяли его. Если в следующее мгновение после вашего успешного пинга интернет отключится, что тогда? Нет смысла проверять перед этим.
dbasnett
12
И как это противоречит основному утверждению моего ответа?
Лев
10
Использование "google.com" займет больше времени, поскольку его необходимо решить. Вместо этого пинг напрямую с использованием IP будет быстрее. Пинг в Google Public DNS IP-адреса ( 8.8.8.8или 8.8.4.4) работает нормально для меня.
Мангеш
8
Я хотел бы еще раз подчеркнуть, что Beware - many schools and offices block the ping protocol.если вы используете этот метод для приложения, которое будет использоваться клиентами, я бы посоветовал не использовать этот метод проверки интернета
user1
42

Вместо проверки просто выполните действие (веб-запрос, почта, ftp и т. Д.) И будьте готовы к сбою запроса, который вы должны будете выполнить в любом случае, даже если проверка прошла успешно.

Учтите следующее:

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

Если сеть не работает, ваше действие будет так же быстро, как пинг и т. Д.

1 - start to perform action
2 - if the net is down(or goes down) the action will fail
dbasnett
источник
9
Правильно! Просто сделай это - но будь готов ко всем результатам.
полковник Паник
3
Рассмотрим следующее: Вам нужно Do Something , если сеть вниз по х amout времени (например , tracelog, маршрутизатор сброса)
Абир
2
Не ОП, но причина, по которой я хочу это сделать, - ИЗБЕГАТЬ ВТОРОГО ВРЕМЕНИ ПО УМОЛЧАНИЮ 100, если подключение к Интернету недоступно. HTTP-запрос выполняется в фоновом потоке, поэтому поток пользовательского интерфейса не блокируется, но мое приложение не может выйти, пока фоновый поток не вернется из HTTP-запроса и не завершится. Вместо того, чтобы пытаться найти какое-то значение тайм-аута «happy medium», я бы хотел просто полностью избежать запроса, если бы знал, что интернет-соединение не работает.
Скотт Смит
2
Моя точка зрения заключалась в том, что мы не можем учитывать, когда удаленная служба может стать доступной / недоступной. Кроме того, как насчет сайтов, которые не отвечают на пинги?
dbasnett
Другой вариант использования - онлайн-проверка, которая предупредит меня, как только мой интернет восстановится
Бен Филипп
28

NetworkInterface.GetIsNetworkAvailableочень ненадежный Просто подключите VMware или другую локальную сеть, и она вернет неправильный результат. Также о Dns.GetHostEntryметоде, который меня беспокоил, может ли тестовый URL быть заблокирован в среде, в которой будет развернуто мое приложение.

Итак, другой способ, который я узнал, - это использование InternetGetConnectedStateметода Мой код

[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);         
}
Камран Шахид
источник
Во время тестирования я обнаружил, что InternetGetConnectedState вернул true, когда был установлен проигрыватель VMWare (Интернет отключен). Пришлось отключить его в Панели управления \ Сеть и Интернет \ Сетевые подключения (VMNet1 и VMNet8).
HockeyJ
Хорошо, Джастин Орингер. Хотя я проверил это, но должен проверить еще раз
Кямран Шахид
2
Лучший подход для меня, после этого я все еще проверяю подключение к сервису, затем запускаю процедуры ... Я просто хотел избежать исключений.
Вагнер Бертолини Джуниор
4
Этот код только проверяет, подключен ли сетевой кабель.
HackerMan
14

Тест для подключения к интернету с помощью пинг Google:

new Ping().Send("www.google.com.mx").Status == IPStatus.Success
Хайме Макиас
источник
7
Описание, сопровождающее этот ответ, было бы полезно для большего количества людей, чем просто первоначальный автор вопроса.
Boeckm
13
Осторожно - многие школы и офисы блокируют протокол пинга. Глупо, я знаю.
Полковник Паник
Я не могу найти класс пинга. не могли бы вы мне помочь. Я работаю над UWP, а другие способы прохождения через сеть информации не работают
iam.Carrot
12

Я не согласен с людьми, которые заявляют: «Какой смысл проверять подключение перед выполнением задачи, так как сразу после проверки соединение может быть потеряно». Конечно, существует определенная степень неопределенности во многих задачах программирования, которые мы, как разработчики, берем на себя, но уменьшение этой неопределенности до уровня приемлемости является частью проблемы.

Недавно я столкнулся с этой проблемой при создании приложения, включающего функцию сопоставления, которая связана с онлайн-сервером плиток. Эта функция должна была быть отключена, когда было отмечено отсутствие подключения к Интернету.

Некоторые ответы на этой странице были очень хорошими, но, тем не менее, вызывали много проблем с производительностью, таких как зависание, в основном в случае отсутствия подключения.

Вот решение, которое я в итоге использовал, с помощью некоторых из этих ответов и моих коллег:

         // 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
            }));
        }
    }
PJRobot
источник
11

Я видел все варианты, перечисленные выше, и единственная реальная возможность проверить, доступен ли Интернет или нет, это опция «Пинг». Импортирование [DllImport("Wininet.dll")]и / System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces() или любое другое изменение NetworkInterface класса не помогает определить доступность сети. Эти методы только проверяют, подключен ли сетевой кабель или нет.

Опция "Пинг"

if(Соединение доступно) возвращает true

if(Соединение недоступно и сетевой кабель подключен) возвращает false

if(Сетевой кабель не подключен) Throws an exception

Сетевой интерфейс

if(Интернет доступен) Возвращает True

if(Интернет недоступен и сетевой кабель подключен) Возвращает True

if(Сетевой кабель не подключен) возвращает false

[DllImport ("Wininet.dll")]

if(Интернет доступен) Возвращает True

if(Интернет недоступен и сетевой кабель подключен) Возвращает True

if(Сетевой кабель не подключен) возвращает false

Так что в случае [DllImport("Wininet.dll")] и NetworkInterface нет никакого способа узнать, доступно ли подключение к интернету.

HackerMan
источник
Это не правда, я импортировал Wininet.dll, подключил сетевой кабель и получил правильный результат для сценария Интернет недоступен.
Вальдемар Галензиновски
8

Не решает проблему сбоя сети между проверкой и запуском вашего кода, но достаточно надежна

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;
}
Антон
источник
Отличная идея, но, как вы сказали, не может быть идеальным. Вы можете также кэшировать отправленные / полученные байты для будущих проверок. Все еще не совершенен все же
Тодд
Этот код не работает, пожалуйста, исправьте. Он только проверяет, подключен ли сетевой кабель или нет.
HackerMan
5

Пинг google.com вводит зависимость разрешения DNS. Pinging 8.8.8.8 - это нормально, но Google находится в нескольких шагах от меня. Все, что мне нужно сделать, это пинговать ближайшую ко мне вещь, которая есть в интернете.

Я могу использовать функцию TTL в Ping для проверки связи № 1, затем перехода № 2 и т. Д., Пока не получу ответ от чего-то, что находится на маршрутизируемом адресе; если этот узел находится на маршрутизируемом адресе, то он находится в Интернете. Для большинства из нас переход № 1 будет нашим локальным шлюзом / маршрутизатором, а переход № 2 будет первой точкой на другой стороне нашего оптоволоконного соединения или чем-то еще.

Этот код работает для меня, и отвечает быстрее, чем некоторые другие предложения в этой теме, потому что он пингует все, что ближе всего ко мне в Интернете.

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;
        }
    }
}
Jinlye
источник
4

Вот как это реализовано в Android.

В качестве подтверждения концепции я перевел этот код на 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
    }
}
Breez
источник
3
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;
    }
}
Шай Сегев
источник
2

Другой вариант - API-интерфейс Network List Manager, который доступен для Vista и Windows 7. Статья MSDN здесь . В статье есть ссылка для скачивания примеров кода, которые позволяют сделать это:

AppNetworkListUser nlmUser = new AppNetworkListUser();
Console.WriteLine("Is the machine connected to internet? " + nlmUser.NLM.IsConnectedToInternet.ToString());

Обязательно добавьте ссылку на библиотеку типов сети List 1.0 на вкладке COM, которая будет отображаться как NETWORKLIST.

Гиров
источник
7
eeeeww. Использование COM ад в .NET?
jgauffin
@jgauffin Можете ли вы объяснить, почему следует избегать COM в .NET? По сравнению с другими решениями, которые я нашел, решение COM, кажется, работает довольно хорошо.
inexcitus
2

Старайтесь избегать тестирования соединений, перехватывая исключение. потому что мы действительно ожидаем, что иногда мы можем потерять подключение к сети.

 if (NetworkInterface.GetIsNetworkAvailable() &&
     new Ping().Send(new IPAddress(new byte[] { 8, 8, 8, 8 }),2000).Status == IPStatus.Success)
 //is online
 else
 //is offline
Шервин Ивари
источник
1
Откуда берется NetworkInterface? РЕДАКТИРОВАТЬ: Я нахожу это: System.Net.NetworkInformation
inspire_coding
1

Лично я считаю, что Антон и Моффельте лучше всего отвечают , но я добавил проверку, чтобы исключить виртуальные сети, созданные VMWare и другими.

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));
}
Spegeli
источник
К сведению: из документа GetIsNetworkAvailable (): сетевое соединение считается доступным, если какой-либо сетевой интерфейс помечен как «вверх» и не является петлевым или туннельным интерфейсом. Я не знаю, будет ли виртуальный всегда указывать имя или описание интерфейса. Это стандарт?
Майк Чил
1
bool bb = System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable();

if (bb == true)
    MessageBox.Show("Internet connections are available");
else
    MessageBox.Show("Internet connections are not available");
Хари Прасат
источник
1
Можете ли вы добавить информацию, касающуюся скорости этого и того, как это лучше, чем другие опубликованные решения. Это поможет вашему ответу полностью ответить на вопрос.
Рен
8
Проблема с этой опцией заключается в том, bbчто все равно будет верно, даже если сеть не подключена к Интернету.
halfpastfour.am
2
Хотя это правда, что это не дает прямого ответа на вопрос, я думаю, что все же полезно использовать GetIsNetworkAvailable в качестве предварительной проверки перед попыткой пропинговать Google и т. Д.
Бен Хьюз
3
В этом коде не указано, доступно или нет подключение к Интернету. Если вы подключите сетевой кабель без интернета, он вернет true.
HackerMan
1

Многопоточная версия 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";
          }
      }
  }
Облако Ним
источник
0

Я не думаю, что это невозможно, просто не так просто.

Я построил что-то вроде этого, и да, это не идеально, но первый шаг важен: проверить, есть ли сетевое подключение. Windows Api не делает большую работу, так почему бы не сделать лучшую работу?

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;
}

Это довольно просто, но действительно помогает улучшить качество проверки, особенно когда вы хотите проверить различные конфигурации прокси.

Так:

  • Проверьте, есть ли подключение к сети (сделайте это действительно хорошим, возможно, даже отправляйте журналы разработчикам, когда есть ложные срабатывания для улучшения функции NetworkIsAvailable)
  • HTTP Ping
  • (Прокрутка прокси-конфигураций с HTTP-пингами на каждом)
Тодд
источник
1
@ hackerman это неочевидный первый шаг. В качестве второго шага кодеры могут выполнить быстрый пинг к своему собственному серверу, если он возвращает true. Важно отметить, что это альтернатива методу api с ошибочными окнами. Остальные детали.
Тодд
3
Подделать. Если нет сетевого интерфейса, то точно нет интернета. Пользовательский интерфейс может быть обновлен сразу же, без каких-либо задержек, без дальнейших проверок на других хостах.
Тодд
0
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;
    }
}
Салих Алия
источник
Пожалуйста, прокомментируйте свой ответ. Ответы только с кодом не допускаются.
ganchito55
Это довольно самоочевидно, охрана ради полиции?
катится
0

Используйте NetworkMonitor для мониторинга состояния сети и интернет-соединения.

Образец:

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");
        }
    }
}

источник
Хорошая идея, но проверяет доступность сети, а не доступность интернета
Джон Деметриу
Этот класс также проверяет доступность Интернета: SourceCode
дело в том, что я попробовал, но он срабатывал только при отсутствии доступной сети
Джон Деметриу
0

Введение

В некоторых сценариях вам необходимо проверить, доступен ли Интернет или нет, используя код C # в приложениях Windows. Может быть, чтобы загрузить или загрузить файл через Интернет в формах Windows или получить некоторые данные из базы данных, которая находится в удаленном месте, в этих ситуациях проверка интернета является обязательной.

Есть несколько способов проверить доступность Интернета с помощью C # из кода. Все такие способы описаны здесь, включая их ограничения.

  1. InternetGetConnectedState (WinInet)

API 'wininet' можно использовать для проверки наличия или отсутствия локальной системы с подключением к Интернету. Используемое для этого пространство имен - System.Runtime.InteropServices и импортируйте dll «wininet.dll» с помощью DllImport. После этого создайте логическую переменную с extern static с именем функции InternetGetConnectedState с описанием двух параметров и reservedValue, как показано в примере.

Примечание. Модификатор extern используется для объявления метода, который реализован извне. Обычно используется модификатор extern с атрибутом DllImport, когда вы используете сервисы Interop для вызова неуправляемого кода. В этом случае метод также должен быть объявлен как статический.

Затем создайте метод с именем IsInternetAvailable в качестве логического значения. Вышеупомянутая функция будет использоваться в этом методе, который возвращает интернет-статус локальной системы

[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;
    }
}
  1. GetIsNetworkAvailable

В следующем примере метод GetIsNetworkAvailable используется для определения доступности сетевого подключения.

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");
}

Примечания (согласно MSDN): сетевое соединение считается доступным, если какой-либо сетевой интерфейс помечен как «вверх» и не является петлевым или туннельным интерфейсом.

Во многих случаях устройство или компьютер не подключены к полезной сети, но все еще считаются доступными, и GetIsNetworkAvailable возвращает значение true. Например, если устройство, на котором запущено приложение, подключено к беспроводной сети, для которой требуется прокси-сервер, но прокси-сервер не задан, GetIsNetworkAvailable вернет значение true. Другой пример того, когда GetIsNetworkAvailable вернет true, - это если приложение работает на компьютере, который подключен к концентратору или маршрутизатору, где концентратор или маршрутизатор потерял восходящее соединение.

  1. Пингуйте имя хоста в сети

Классы Ping и PingReply позволяют приложению определять, доступен ли удаленный компьютер по сети, путем получения ответа от хоста. Эти классы доступны в пространстве имен System.Net.NetworkInformation. В следующем примере показано, как проверить связь с хостом.

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;
}

Примечания (согласно MSDN). Приложения используют класс Ping для определения доступности удаленного компьютера. Топология сети может определить, может ли Ping успешно связаться с удаленным хостом. Наличие и настройка прокси-серверов, оборудования для преобразования сетевых адресов (NAT) или брандмауэров могут помешать выполнению Ping. Успешный Ping указывает только на то, что удаленный хост может быть доступен в сети; присутствие сервисов более высокого уровня (таких как веб-сервер) на удаленном хосте не гарантируется.

Комментарии / предложения приветствуются. Удачного кодирования ......!

Хурам Шахзад
источник
-1

Для моего приложения мы также тестируем путем загрузки крошечного файла.

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;
}

Также. Некоторые интернет-провайдеры могут использовать промежуточный сервер для кэширования файла. Добавить случайный неиспользуемый параметр, например. https://www.microsoft.com/favicon.ico?req=random_number Может предотвратить кэширование.

user282341
источник
-1

У меня проблема с этим методом на моем 3G маршрутизаторе / модеме, потому что, если интернет отключен, маршрутизатор перенаправляет страницу на свою страницу ответа, так что вы все равно получаете пар и ваш код думает, что есть интернет. У яблок (или других) есть страница определения горячих точек, которая всегда возвращает определенный ответ. Следующий пример возвращает ответ «Успех». Таким образом, вы будете точно уверены, что сможете подключиться к Интернету и получить реальный ответ!

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;
}
Юсуф ГУРДАГ
источник
-2

У меня есть три теста для подключения к Интернету.

  • Ссылка System.NetиSystem.Net.Sockets
  • Добавьте следующие тестовые функции:

Тест 1

public bool IsOnlineTest1()
{
    try
    {
        IPHostEntry dummy = Dns.GetHostEntry("https://www.google.com");
        return true;
    }
    catch (SocketException ex)
    {
        return false;
    }
}

Тест 2

public bool IsOnlineTest2()
{
    try
    {
        IPHostEntry dummy = Dns.GetHostEntry("https://www.google.com");
        return true;
    }
    catch (SocketException ex)
    {
        return false;
    }
}

Тест 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;
    }
}

Выполнение тестов

Если вы сделаете Dictionaryиз Stringи Booleanпозвонили CheckList, вы можете добавить результаты каждого теста в CheckList.

Теперь пройдитесь по каждому из них, KeyValuePairиспользуя for...eachцикл.

Если CheckListсодержит Valueо true, то вы знаете, что есть подключение к Интернету.

М. Ливиу
источник
-4
public static bool HasConnection()
{
    try
    {
        System.Net.IPHostEntry i = System.Net.Dns.GetHostEntry("www.google.com");
        return true;
    }
    catch
    {
        return false;
    }
}

Это работает

slayerIQ
источник
46
Если у вас есть IP-адрес Google в вашем DNS-кэше, он не будет отправлять DNS-запрос, поэтому он может вернуть true, даже если вы не подключены
Thomas Levesque