Каков наилучший способ проверить подключение к Интернету с помощью .NET? - PullRequest
203 голосов
/ 09 января 2010

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

Ответы [ 24 ]

253 голосов
/ 09 января 2010

Как-то так должно работать.

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;
    }
}
72 голосов
/ 09 января 2010

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

Однако вы можете запросить ресурсы, которые практически никогда не отключены, например, 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;
}
37 голосов
/ 31 января 2010

Вместо проверки просто выполните действие (веб-запрос, почта, 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
26 голосов
/ 11 сентября 2014

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);         
}
12 голосов
/ 13 ноября 2012

Проверка подключения к интернету с помощью pinging Google:

new Ping().Send("www.google.com.mx").Status == IPStatus.Success
11 голосов
/ 11 апреля 2014

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

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

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

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

         // 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 голосов
/ 21 ноября 2016

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

«Опция Ping»

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

8 голосов
/ 29 июня 2014

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

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;
}
4 голосов
/ 17 мая 2017

Вот , как это реализовано в 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
    }
}
3 голосов
/ 08 сентября 2016
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;
    }
}
...