WinForms: уведомление, когда доступ к Интернету становится доступным, а не сетевое подключение [дублировать]

В следующем примере, который я написал, показано, как

  • обрабатывать асинхронные HTTP-вызовы;
  • Подождать ответа от каждого вызова API;
  • Использовать шаблон promise ;
  • Используйте шаблон Promise.All для объединения нескольких HTTP-вызовов;

Этот рабочий пример является автономным. Он будет определять простой объект запроса, который использует объект window XMLHttpRequest для совершения вызовов. Он будет определять простую функцию, чтобы дождаться завершения кучи обещаний.

Контекст. В этом примере запрашивается конечная точка Spotify Web API для поиска объектов playlist для заданного набора строк запроса:

[
 "search?type=playlist&q=%22doom%20metal%22",
 "search?type=playlist&q=Adele"
]

Для каждого элемента новый Promise запустит блок - ExecutionBlock, проанализирует результат, заплатит новый набор обещаний на основе массива результатов, который представляет собой список объектов Spotify user и выполняет новый HTTP-вызов в ExecutionProfileBlock асинхронно.

Затем вы можете увидеть вложенную структуру Promise, которая позволяет вам генерировать множественные и полностью асинхронные вложенные HTTP-вызовы и присоединять результаты к каждому подмножеству вызовов через Promise.all.

NOTE Recent Spotify search API-интерфейсам потребуется указать токен доступа в заголовках запроса:

-H "Authorization: Bearer {your access token}" 

Итак, вы должны запустить следующий пример, вам нужно поместить маркер доступа в заголовки запроса:

var spotifyAccessToken = "YourSpotifyAccessToken";
var console = {
    log: function(s) {
        document.getElementById("console").innerHTML += s + "
" } } // Simple XMLHttpRequest // based on https://davidwalsh.name/xmlhttprequest SimpleRequest = { call: function(what, response) { var request; if (window.XMLHttpRequest) { // Mozilla, Safari, ... request = new XMLHttpRequest(); } else if (window.ActiveXObject) { // Internet Explorer try { request = new ActiveXObject('Msxml2.XMLHTTP'); } catch (e) { try { request = new ActiveXObject('Microsoft.XMLHTTP'); } catch (e) {} } } // State changes request.onreadystatechange = function() { if (request.readyState === 4) { // Done if (request.status === 200) { // Complete response(request.responseText) } else response(); } } request.open('GET', what, true); request.setRequestHeader("Authorization", "Bearer " + spotifyAccessToken); request.send(null); } } //PromiseAll var promiseAll = function(items, block, done, fail) { var self = this; var promises = [], index = 0; items.forEach(function(item) { promises.push(function(item, i) { return new Promise(function(resolve, reject) { if (block) { block.apply(this, [item, index, resolve, reject]); } }); }(item, ++index)) }); Promise.all(promises).then(function AcceptHandler(results) { if (done) done(results); }, function ErrorHandler(error) { if (fail) fail(error); }); }; //promiseAll // LP: deferred execution block var ExecutionBlock = function(item, index, resolve, reject) { var url = "https://api.spotify.com/v1/" url += item; console.log( url ) SimpleRequest.call(url, function(result) { if (result) { var profileUrls = JSON.parse(result).playlists.items.map(function(item, index) { return item.owner.href; }) resolve(profileUrls); } else { reject(new Error("call error")); } }) } arr = [ "search?type=playlist&q=%22doom%20metal%22", "search?type=playlist&q=Adele" ] promiseAll(arr, function(item, index, resolve, reject) { console.log("Making request [" + index + "]") ExecutionBlock(item, index, resolve, reject); }, function(results) { // Aggregated results console.log("All profiles received " + results.length); //console.log(JSON.stringify(results[0], null, 2)); ///// promiseall again var ExecutionProfileBlock = function(item, index, resolve, reject) { SimpleRequest.call(item, function(result) { if (result) { var obj = JSON.parse(result); resolve({ name: obj.display_name, followers: obj.followers.total, url: obj.href }); } //result }) } //ExecutionProfileBlock promiseAll(results[0], function(item, index, resolve, reject) { //console.log("Making request [" + index + "] " + item) ExecutionProfileBlock(item, index, resolve, reject); }, function(results) { // aggregated results console.log("All response received " + results.length); console.log(JSON.stringify(results, null, 2)); } , function(error) { // Error console.log(error); }) ///// }, function(error) { // Error console.log(error); });

Я подробно рассмотрел это решение здесь .

181
задан Palec 7 August 2014 в 21:50
поделиться

14 ответов

Что-то вроде этого должно работать.

System.Net.WebClient

public static bool CheckForInternetConnection()
{
    try
    {
        using (var client = new WebClient())
        using (client.OpenRead("http://clients3.google.com/generate_204"))
        {
            return true;
        }
    }
    catch
    {
        return false;
    }
}
226
ответ дан Micaël Félix 28 August 2018 в 07:02
поделиться

Вот , как это реализовано в 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
    }
}
2
ответ дан breez 28 August 2018 в 07:02
поделиться

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

  • Ссылка 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, то вы знаете, что есть подключение к Интернету.

3
ответ дан Cody Gray 28 August 2018 в 07:02
поделиться

Тест для подключения к Интернету путем проверки Google:

new Ping().Send("www.google.com.mx").Status == IPStatus.Success
9
ответ дан Colonel Panic 28 August 2018 в 07:02
поделиться

Вместо проверки просто выполните действие (веб-запрос, почту, 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
27
ответ дан dbasnett 28 August 2018 в 07:02
поделиться

У меня проблема с этим методом на моем маршрутизаторе / модеме 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;
}
-1
ответ дан Dmitry Volkov 28 August 2018 в 07:02
поделиться

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

Параметр «Ping»

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

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

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

NetworkInterface

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

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

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

[DllImport («Wininet.dll»)]

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

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

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

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

4
ответ дан HackerMan 28 August 2018 в 07:02
поделиться

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

Я могу использовать функцию TTL Ping для ping hop # 1, then hop # 2 и т. д., пока не получаю ответ от чего-то, что находится на маршрутизируемом адресе; если этот узел находится на маршрутизируемом адресе, то он находится в Интернете. Для большинства из нас, хоп # 1 будет нашим локальным шлюзом / маршрутизатором, а hop # 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;
        }
    }
}
2
ответ дан Jinlye 28 August 2018 в 07:02
поделиться

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

Вы можете, однако, запросить ресурсы, которые практически никогда не работают в автономном режиме , например, 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;
}
61
ответ дан Leo 28 August 2018 в 07:02
поделиться

Многопоточная версия 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
ответ дан Nime Cloud 28 August 2018 в 07:02
поделиться

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

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

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

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

         // 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
            }));
        }
    }
9
ответ дан PJRobot 28 August 2018 в 07:02
поделиться
public static bool HasConnection()
{
    try
    {
        System.Net.IPHostEntry i = System.Net.Dns.GetHostEntry("www.google.com");
        return true;
    }
    catch
    {
        return false;
    }
}

Это работает

-3
ответ дан slayerIQ 28 August 2018 в 07:02
поделиться

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

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 Может предотвратить кеширование.

-1
ответ дан user282341 28 August 2018 в 07:02
поделиться

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

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;
}
18
ответ дан Vadim Ovchinnikov 28 August 2018 в 07:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: