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

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


person Mohit Deshpande    schedule 09.01.2010    source источник
comment
Если у пользователя есть подключение к Интернету. Если пользователь может подключиться к Интернету. Чтобы отправить журнал по электронной почте.   -  person Mohit Deshpande    schedule 09.01.2010
comment
Просто отправьте электронное письмо. Если пользователь не подключен, вы, скорее всего, получите какое-то исключение (которое вам, вероятно, все равно придется обрабатывать).   -  person Seth    schedule 09.01.2010
comment
Также обратите внимание, что нет способа проверить, подключен ли пользователь к Интернету; все, что вы можете сказать, - это были ли они связаны в прошлом. Предположим, у вас есть метод: bool c = IsConnected (); if (c) {DoSomething (); } - между вызовом IsConnected и DoSomething маршрутизатор беспроводной сети мог быть отключен. IsConnected действительно следует называть WasRecentlyConnected.   -  person Eric Lippert    schedule 09.01.2010
comment
Windows NLM API должен быть лучшим для этого. stackoverflow.com/questions/5405895/   -  person Mahbubur Rahman    schedule 08.03.2020
comment
Не зная вашего варианта использования, вам, вероятно, будет разумнее больше беспокоиться о том, что брандмауэры не блокируют доступ к серверам, которые вам нужны, а не к Интернету в целом.   -  person Chiramisu    schedule 22.09.2020


Ответы (26)


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

Однако вы можете запрашивать ресурсы, которые практически никогда не отключены, например, 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;
}
person Leo    schedule 09.01.2010
comment
+1 Нет абсолютно никакой возможности надежно проверить, есть ли интернет-соединение - person woz; 19.03.2013
comment
Все, что нужно сделать, это проверить, что Google активен, когда вы его выполнили. Если в следующий момент после успешного пинга интернет выйдет из строя, что тогда? Проверять перед тем как делать нет смысла. - person dbasnett; 14.05.2013
comment
И как это противоречит основному утверждению моего ответа? - person Leo; 14.05.2013
comment
Использование google.com займет больше времени, потому что необходимо решить эту проблему. Вместо этого пинг напрямую с использованием IP будет быстрее. Пинг на IP-адреса Google Public DNS (8.8.8.8 или 8.8.4.4) у меня работает нормально. - person Mangesh; 16.01.2015
comment
По моему опыту, 1000 миллисекунд для тайм-аута слишком мало, и для медленных / высокоскоростных интернет-соединений это может сообщать неверно. - person user1; 27.04.2015
comment
Я хотел бы повторить, что Beware - many schools and offices block the ping protocol. Если вы используете этот метод для приложения, которое будет использоваться клиентами, я бы посоветовал не использовать этот метод проверки в Интернете. - person user1; 29.04.2015
comment
Пинг - это хорошее первое, что можно попробовать, но исходящий PING заблокирован во многих школах и компаниях, поэтому ваш код должен возвращаться к HTTP-запросу (предпочтительно к сайту, с которым вы планируете поговорить, а не только к Google. com) в случае сбоя PING. Кроме того, само разрешение DNS может занять до 20 секунд, так что это минимальное значение тайм-аута; то есть более низкие значения тайм-аута могут все еще занять 20 секунд, прежде чем метод вернется. - person Scott Smith; 11.05.2015
comment
Оптимизировать такой подход нет абсолютно никакого смысла. В любом случае попробуйте делать то, что вы хотели; действуйте соответственно, если это не удается. Период. - person Leo; 11.05.2015
comment
Есть ли способ реализовать это асинхронно? использование SendAsync жалуется, что не может преобразовать void в PingReply. - person tCoe; 16.09.2019
comment
@Leo Это довольно опрометчивое заявление. Я бы счел свой вариант использования вполне допустимым: онлайн-средство проверки, которое предупредит меня и выполнит действия, как только Интернет будет восстановлен. - person Ben Philipp; 15.12.2019
comment
Это решение работает намного быстрее (1-10 мс) по сравнению с другими. Также изменение с google.com на прямой DNS-сервер, например 1.1.1.1, имеет большое значение. Вы можете найти в Google самый быстрый DNS - person Semertzidis Aris; 29.06.2021

Вместо проверки просто выполните действие (веб-запрос, почта, 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
person dbasnett    schedule 31.01.2010
comment
Верно! Просто сделайте это - но будьте готовы ко всем результатам. - person Colonel Panic; 28.02.2013
comment
Примите во внимание следующее: вам необходимо сделать что-нибудь, если сеть не работает в течение некоторого времени (например, журнал трассировки, сброс маршрутизатора) - person Abir; 01.04.2015
comment
Не OP, но причина, по которой я хочу это сделать, состоит в том, чтобы ИЗБЕЖАТЬ 100-секундного тайм-аута по умолчанию, если подключение к Интернету недоступно. HTTP-запрос выполняется в фоновом потоке, поэтому поток пользовательского интерфейса не блокируется, но мое приложение не может выйти, пока фоновый поток не вернется из HTTP-запроса и не завершится. Вместо того, чтобы пытаться найти какое-то значение тайм-аута «золотой середины», я хотел бы вообще избежать запроса, если бы я знал, что подключение к Интернету разорвано. - person Scott Smith; 11.05.2015
comment
Я хотел сказать, что мы не можем учитывать, когда удаленная служба может стать доступной / недоступной. А как насчет сайтов, которые не отвечают на пинги? - person dbasnett; 12.05.2015
comment
Другой вариант использования - онлайн-проверка, которая предупредит меня, как только мой интернет будет восстановлен. - person Ben Philipp; 15.12.2019
comment
Конечно, полезно понимать разницу между тем, что клиент не может подключиться к вашей конкретной веб-службе, а клиент вообще не может подключиться к Интернету. Причина, по которой я смотрю на это через 10 лет, заключается в том, что я хочу, чтобы локальное приложение имело другое поведение при запуске, если моя веб-служба не работает, и если она не может получить доступ к сети; как вы должны быть готовы, если не знаете, что произошло? - person Lovethenakedgun; 20.02.2020

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);         
}
person Kamran Shahid    schedule 11.09.2014
comment
Во время тестирования я обнаружил, что InternetGetConnectedState вернул true, когда был установлен проигрыватель VMWare (интернет отключен). Пришлось отключить его в Control Panel \ Network and Internet \ Network Connections (VMNet1 и VMNet8). - person HockeyJ; 10.06.2015
comment
Хорошо, Джастин Оринджер. Хотя я проверил это, но мне нужно проверить еще раз - person Kamran Shahid; 10.06.2015
comment
Лучший подход для меня, после этого я все еще проверяю подключение к своей службе, затем запускаю процедуры ... Я просто хотел избежать исключений. - person Wagner Bertolini Junior; 24.05.2016
comment
Этот код только проверяет, подключен ли сетевой кабель. - person HackerMan; 21.11.2016
comment
Этот код не переносится на Linux, MacOS. - person weePee; 13.05.2021
comment
Привет @weePee, я знаю, что вы пробуете это с ядром .net, тогда помните, что этот пост - до эпохи ядра .net 2014 года - person Kamran Shahid; 14.05.2021

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

new Ping().Send("www.google.com.mx").Status == IPStatus.Success
person Jaime Macias    schedule 13.11.2012
comment
Описание, сопровождающее этот ответ, будет полезно большему количеству людей, чем только первоначальный автор вопроса. - person Boeckm; 13.11.2012
comment
Остерегайтесь - многие школы и офисы блокируют протокол ping. Я знаю, это глупо. - person Colonel Panic; 28.02.2013
comment
Я не могу найти класс ping. Не могли бы вы мне помочь. Я работаю над UWP, и другие способы просмотра сетевой информации не работают - person iam.Carrot; 03.11.2016

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

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

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

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

         // 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
            }));
        }
    }
person PJRobot    schedule 11.04.2014

Я видел все варианты, перечисленные выше, и единственный жизнеспособный вариант проверить, доступен ли Интернет или нет, - это вариант «Пинг». Импорт [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 невозможно узнать, доступно ли подключение к Интернету.

person HackerMan    schedule 21.11.2016
comment
Это неправда, я импортировал Wininet.dll, подключил сетевой кабель и получил правильный результат для сценария, когда Интернет недоступен. - person Waldemar Gałęzinowski; 02.02.2019

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

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

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


using System.Diagnostics;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Threading.Tasks;
    
public static async Task<bool> IsConnectedToInternetAsync()
{
    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++)
    {
        var options = new PingOptions(ttl, true);
        byte[] buffer = new byte[32];
        PingReply reply;
        try
        {
            using (var pinger = new Ping())
            {
                reply = await pinger.SendPingAsync(someFarAwayIpAddress, 10000, buffer, options);
            }
        }
        catch (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;
        }
    
        string address = reply.Address?.ToString() ?? null;
        Debug.Print($"Hop #{ttl} is {address}, {reply.Status}");
    
        if (reply.Status != IPStatus.TtlExpired && reply.Status != IPStatus.Success)
        {
            Debug.Print($"Hop #{ttl} is {reply.Status}, hence we are not connected.");
            return false;
        }
    
        if (isRoutableAddress(reply.Address))
        {
            Debug.Print("That's routable, so we 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;
        }
    }
}
person Jinlye    schedule 29.09.2016
comment
Это интересный подход, и он сильно отличается от других ответов! (+1) - person AnorZaken; 26.03.2021

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

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;
}
person Anton    schedule 29.06.2014
comment
Отличная идея, но, как вы сказали, может быть не идеальной. Вы также можете кэшировать отправленные / полученные байты для будущих проверок. Тем не менее, все еще не идеально. - person Todd; 05.10.2015
comment
Этот код не работает, исправьте. Он только проверяет, подключен ли сетевой кабель. - person HackerMan; 21.11.2016
comment
(Согласно MSDN): сетевое соединение считается доступным, если какой-либо сетевой интерфейс размечен и не является интерфейсом обратной связи или туннеля. Помимо проверки BytesSent и BytesReceived, вы в основном просто дублировали функциональность, которая уже есть в GetIsNetworkAvailable. - person AnorZaken; 26.03.2021

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

 if (NetworkInterface.GetIsNetworkAvailable() &&
     new Ping().Send(new IPAddress(new byte[] { 8, 8, 8, 8 }),2000).Status == IPStatus.Success)
 //is online
 else
 //is offline
person Shervin Ivari    schedule 18.03.2020
comment
Откуда приходит NetworkInterface? РЕДАКТИРОВАТЬ: Я нахожу это: System.Net.NetworkInformation - person inspire_coding; 15.04.2020

Вот, как это реализовано в 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
    }
}
person breez    schedule 17.05.2017

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

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

Обязательно добавьте ссылку на Библиотеку типов списка сетей 1.0 на вкладке COM ... которая будет отображаться как СПИСОК СЕТИ.

person gierow    schedule 19.03.2013
comment
eeeeww. Используете ад COM в .NET? - person jgauffin; 29.06.2014
comment
@jgauffin Можете ли вы объяснить, почему следует избегать COM в .NET? По сравнению с другими найденными мною решениями, решение COM работает довольно хорошо. - person inexcitus; 20.05.2019

Я бы не подумал, что это невозможно, просто непросто.

Я построил что-то подобное, и да, это не идеально, но первый шаг важен: проверить, есть ли какое-либо сетевое подключение. 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;
}

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

So:

  • Проверьте, есть ли подключение к сети (сделайте это действительно хорошо, возможно, даже отправьте журналы обратно разработчикам, когда есть ложные срабатывания, чтобы улучшить функцию NetworkIsAvailable)
  • HTTP-пинг
  • (Циклическое переключение конфигураций прокси с HTTP-запросами на каждом)
person Todd    schedule 05.10.2015
comment
@hackerman, это неочевидный первый шаг. Кодеры могут выполнить быстрый пинг на свой собственный сервер, если он вернет true, в качестве второго шага. Важно отметить, что это является альтернативой некорректному методу API Windows. Остальное - детали. - person Todd; 21.11.2016
comment
Подделать. Если сетевой интерфейс не работает, значит, Интернета точно нет. Пользовательский интерфейс может быть обновлен сразу же, без каких-либо дополнительных проверок на других хостах. - person Todd; 21.11.2016

Вступление

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

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

  1. InternetGetConnectedState (wininet)

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

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

Затем создайте метод с логическим именем 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 указывает только на то, что удаленный хост доступен в сети; наличие служб более высокого уровня (например, веб-сервера) на удаленном узле не гарантируется.

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

person Khuram Shahzad    schedule 05.04.2020

Если вы хотите уведомлять пользователя / предпринимать действия всякий раз, когда происходит изменение сети / подключения.
Используйте NLM API:

person Ansary Ans21    schedule 31.07.2015

Я лично считаю, что лучше всего отвечает Антон и моффельтье, но я добавил проверку, чтобы исключить виртуальные сети, созданные 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));
}
person Spegeli    schedule 03.04.2017
comment
К сведению, из документации GetIsNetworkAvailable (): сетевое соединение считается доступным, если какой-либо сетевой интерфейс размечен и не является интерфейсом обратной связи или туннеля. Я не знаю, всегда ли virtual будет в названии или описании интерфейса. Это стандарт? - person Mike Cheel; 29.05.2019

Многопоточная версия 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";
          }
      }
  }
person Nime Cloud    schedule 08.08.2018

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

Сообщается, что пинг поддерживается не во всех средах, поэтому я начал с принятого ответа и добавил WebClient из здесь с настраиваемый тайм-аут. Вы можете выбрать любой тайм-аут, но у меня работало 3 секунды при подключении через Wi-Fi. Я попытался добавить быструю итерацию (1 секунду), а затем медленную итерацию (3 секунды), если первая не удалась. Но это не имело смысла, поскольку обе итерации всегда терпели неудачу (когда не были подключены) или всегда заканчивались успехом (когда были подключены).

Я подключаюсь к AWS, так как хочу загрузить файл после прохождения теста подключения.

public static class AwsHelpers
{
    public static bool GetCanConnectToAws()
    {
        try
        {
            using (var client = new WebClientWithShortTimeout())
            using (client.OpenRead("https://aws.amazon.com"))
                return true;
        }
        catch
        {
            return false;
        }
    }
}

public class WebClientWithShortTimeout: WebClient
{
    protected override WebRequest GetWebRequest(Uri uri)
    {
        var webRequest = base.GetWebRequest(uri);
        webRequest.Timeout = 5000;
        return webRequest;
    }
}
person brinkdinges    schedule 01.08.2020

Используйте 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");
        }
    }
}
person Community    schedule 19.09.2018
comment
Хорошая идея, но проверяет доступность сети, а не доступность Интернета - person John Demetriou; 07.02.2019
comment
Этот класс также проверяет доступность Интернета: SourceCode - person ; 13.02.2019
comment
дело в том, что я пробовал, но он срабатывал только в том случае, если сеть не была доступна - person John Demetriou; 14.02.2019

Вы можете использовать метод NetworkInterface.GetIsNetworkAvailable, который указывает, доступно ли какое-либо сетевое соединение.

Попробуй это:

bool connection = NetworkInterface.GetIsNetworkAvailable();
if (connection == true)
 {
     MessageBox.Show("The system is online");
 }
 else {
     MessageBox.Show("The system is offline";
 }
person Mustafa    schedule 12.09.2020
comment
всегда возвращает истину для меня, даже когда я отключаюсь от Wi-Fi - person Yaroslav Dukal; 25.03.2021

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

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

person Sum Settavut    schedule 29.04.2017

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

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;
}
person Yusuf GURDAG    schedule 11.08.2017

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

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

person M. Liviu    schedule 22.06.2017

public static bool HasConnection()
{
    try
    {
        System.Net.IPHostEntry i = System.Net.Dns.GetHostEntry("www.google.com");
        return true;
    }
    catch
    {
        return false;
    }
}

Это работает

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

person    schedule
comment
Это, вероятно, лучше, чем пинговать Google, потому что я думаю, что у нас нет гарантии, что Google продолжит отвечать на пинги. С другой стороны, я не могу представить себе мир, в котором www.google.com не возвращает HTML-код :) - person Daniel Vassallo; 09.01.2010
comment
@Daniel: правда, с одной стороны, но с другой стороны, фактическая загрузка веб-сайта - это немного накладные расходы imo - person Leo; 09.01.2010
comment
4KB - это не очень много накладных расходов. - person ChaosPandion; 09.01.2010
comment
В любом случае нет причин возвращать 4 КБ назад - просто используйте вместо этого client.OpenRead (url). Если он не генерирует исключение, значит, он смог подключиться. - person Josh M.; 27.03.2011
comment
Это всегда возвращает истину для меня .. Даже если я сделаю URL-адрес asdfasdf193287912387 - person Nathan F.; 13.05.2013
comment
Все, что нужно сделать, это проверить, работает ли Google. Если в следующий момент интернет выйдет из строя, что тогда? Проверять перед тем как делать нет смысла. Где-то я читал отчет, что на такого рода бессмысленные упражнения приходится 2% трафика в Интернете. - person dbasnett; 14.05.2013
comment
На самом деле это не так эффективно. Использование этого заставляет мою программу запускаться через 1 минуту, если нет Интернета. Вероятно, из-за попытки разрешить DNS. Пинг 8.8.8.8 (google dns) изменил его на 3 секунды. - person MadBoy; 14.06.2013
comment
Замените оператор using на using (var client = new WebClient() { Proxy = null }) на моем компьютере это будет быстрее;) - person Tono Nam; 25.09.2013
comment
Вы можете сделать этот метод еще более безотказным, добавив больше URL-адресов, таких как www.facebook.com и www.twitter.com, вероятность того, что все три будут недоступны, равна нулю. - person Max; 14.04.2014
comment
Привет, когда я пытаюсь использовать вышеуказанный метод при выполнении 'client.OpenRead (google.com)', Я получаю сообщение об ошибке. Удаленный сервер возвратил ошибку: (502) Bad Gateway. Пожалуйста, помогите мне с этим. - person Hulk; 21.08.2014
comment
Есть ли альтернативный сайт? google.com такой тяжелый. Хотелось бы, чтобы какой-то веб-сайт имел в ответе только пустое тело HTTP и был доступен все время. - person Thraka; 10.09.2014
comment
Если вы тестируете подключение к Интернету, чтобы можно было подключиться к определенному сайту (например, к серверу приложений), то вам следует отправить HTTP-запрос на этот сайт, а не в Google. И да, исходящий PING блокируется некоторыми школами и предприятиями, так что это ненадежный метод. - person Scott Smith; 11.05.2015
comment
Какие преимущества у этого есть по сравнению с System.Net.Sockets.TcpClient? Я имею в виду, что метод WebClient занимает несколько секунд, а TcpClient - <200 мс. System.Net.Sockets.TcpClient client = новый System.Net.Sockets.TcpClient (www.google.com, 80); - person jmelhus; 21.07.2015
comment
Это решение может быть медленным без тайм-аута - person AdrienTorris; 27.04.2016
comment
stackoverflow.com/questions/520347/ - person Kumar; 04.07.2016
comment
@DanielVassallo I cannot image a world where www.google.com does not return some HTML, например, в Китае ... - person Jérôme MEVEL; 27.10.2016
comment
@HackerMan: наше приложение проверяет наличие интернета и выдает ошибку, если что-то упущено и нет интернета для его загрузки. люди в нашем китайском офисе необъяснимо поняли это сообщение. Я удалился и обнаружил, что код в этой проверке возвращает false. переход на саму веб-страницу на своих компьютерах в конечном итоге выдавал страницу с ошибкой, но в приложении она выдавала ложь. я не пробовал регулировать тайм-аут. для них нам придется использовать более локальный URL, например baidu.com - person ikathegreat; 22.11.2016
comment
Почему мы должны доверять этому решению ?! Возможно, сервер Google не работает и не отвечает. Есть ли другое надежное решение, независимое от других веб-сайтов или серверов? - person Mohammad Afrashteh; 25.05.2018
comment
есть ли способ сделать это без каких-либо исключений? Исключений много - person John Demetriou; 06.06.2018
comment
Если ваш DNS сломан, это не будет работать должным образом, используйте вместо этого IP-адрес. - person Nime Cloud; 07.08.2018
comment
Измененная версия: public static bool ConnectedToAnyOf(params System.Uri[] url) { using (var wc = new System.Net.WebClient()) { for (var index = 0; index < url.Length; index++) { try { using (wc.OpenRead(url[index])) { return true; } } catch { } } } return false; } - person Rob; 11.04.2019
comment
@DanielVassallo - Google недоступен из некоторых стран с ограниченным доступом (например, Китай) - person ; 29.11.2019
comment
Могу ли я как-то реализовать для этого тайм-аут? - person Johny Wave; 25.02.2020
comment
Google не отвечает на http://google.com/generate_204 - person Zeeshanef; 09.04.2021

person    schedule
comment
Прокомментируйте, пожалуйста, свой ответ. Ответы только с кодом не допускаются. - person ganchito55; 07.03.2017
comment
Это довольно понятно, полицейские ради полицейских? - person rolls; 25.01.2018

person    schedule
comment
Можете ли вы добавить информацию о скорости этого и о том, насколько это лучше, чем другие опубликованные решения. Это поможет вашему ответу полностью ответить на вопрос. - person Ren; 23.04.2013
comment
Проблема с этой опцией заключается в том, что bb все равно будет истинным, даже если сеть не подключена к Интернету. - person halfpastfour.am; 17.05.2013
comment
Хотя это правда, что это не дает прямого ответа на вопрос, я думаю, что все же полезно использовать GetIsNetworkAvailable в качестве предварительной проверки перед попыткой пинговать Google и т. Д. - person Ben Hughes; 10.10.2013
comment
Этот код не сообщает, доступно ли подключение к Интернету. Если вы подключите сетевой кабель без Интернета, он вернет true. - person HackerMan; 21.11.2016