2009-12-07 3 views
12

Я знаю, что не являюсь первым, кто задает вопрос: Как узнать, подключено ли мое приложение или нет? Я нашел этот пост: StackOverflow. Я хочу сделать это с C# и .NET 3.5.Определите, подходит ли соединение с Интернетом

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

.NET предоставляет два события для этой цели: NetworkChange.NetworkAvailabilityChanged NetworkChange.NetworkAddressChanged

Первое событие звучит хорошо, но это срабатывает только тогда, когда последняя сетевая карта, которая находится на сайте переходит в автономный режим. У меня есть несколько виртуальных сетевых карт, которые были установлены VMWare, и они всегда в сети. Второе событие работает, но между подключением сетевого кабеля и событием часто бывает 5 секунд ожидания. Значок Windows tray реагирует более или менее немедленно, когда я отсоединяю кабель. Каков наилучший способ быть таким быстрым, как этот значок в трее?

Мой обходной путь будет опрашивать NetworkInterface.GetAllNetworkInterfaces() каждые 500 мс и бросить свое собственное мероприятие в случае, когда статус сетевого адаптера изменилось.

Там должен быть лучшим решением :)

+0

Как вы планируете выявлять все соответствующие сетевые изменения? У вашего приложения действительно нет способа узнать, потеряно ли какое-то жизненно важное звено на этом пути. –

+0

См. Мои изменения для новой информации о Iphlpapi.dll и NotifyAddrChange – Webleeuw

+0

Интернет в каком смысле? С сервером? Если вы находитесь в сети с сервером, почему бы просто не отправлять сообщение о состоянии каждые 5 секунд, чтобы определить, находитесь ли вы в сети или нет? – 2009-12-07 14:43:30

ответ

0

Pinging вашего ресурса регулярно является единственным вариантом, который даст вам уведомление, если услуга переходит в автономном режиме, а также, если клиент переходит в автономном режиме. Потенциально вы хотите обрабатывать обе ситуации.

+0

Да, я знаю. Для меня риск того, что сеть конкретного пользователя недоступна, намного выше, чем риск того, что сервер недоступен. Мы будем пинговать, но не регулярно, а только при запуске приложения и при изменении сети. Возможно, мы будем пинговать регулярно, но потом не каждые 500 мс :) – 2009-12-07 13:08:08

0

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

Поскольку сетевая карта является лишь одной из многих связей между вашим клиентом и службой, к которой он обращается в Интернете, единственным надежным способом определить, доступен ли Интернет, является опрос какой-либо услуги в Интернете, почти так же, как и ping. В сетях TCP/IP это известно как keepalive, и многие протоколы будут встроены в них как опция.

0

О пинге: в зависимости от того, как вы хотите интерпретировать результаты, пинг не кажется мне водонепроницаемым. Что, если цель истекает время от времени, пока соединение остается в живых? Я еще не видел сервер, который никогда не реагирует на пинг.

Проверка каждого X-миллиметра, если сетевой интерфейс все еще находится в сети (свойство NetworkInterface.OperationalStatus), кажется более надежным, если вы спросите меня.

EDIT: This статья посвящена событиям сетевых адресов на более низком уровне, чем класс System.Net.NetworkInformation.NetworkChange, или так кажется. На моем компьютере он работает очень быстро, поэтому, надеюсь, вы сможете использовать это решение.

+0

Спасибо за ссылку. Я посмотрел на него. Кажется, что используется NetworkChange. Это полезно, но я не доволен тем, что он слишком медленный. – 2009-12-07 13:38:51

+0

«Я еще не видел сервер, который никогда не отвечает на пинг». Это плохое предположение. Многие сети отбрасывают пакеты ICMP. – 2009-12-07 14:44:21

+0

@Roboto: Я не понимаю ваш комментарий, возможно, из-за небольшого несоответствия общения :). В этом предложении я хотел указать на то, что ping не является надежным, потому что сервер может удалить один или несколько пакетов ping, даже если он в сети. Более ясно: мне еще предстоит увидеть сервер, который всегда и всегда реагирует на каждый пинг, который он отправляет. – Webleeuw

2

Попробуйте это с помощью NetworkChange класса

using System.Net.NetworkInformation 

private void Form5_Load(object sender, EventArgs e) 
{ 
    NetworkChange.NetworkAvailabilityChanged += new NetworkAvailabilityChangedEventHandler(NetworkChange_NetworkAvailabilityChanged); 
} 

private void NetworkChange_NetworkAvailabilityChanged(object sender, NetworkAvailabilityEventArgs e) 
{ 
    if (e.IsAvailable) 
    { 
     MessageBox.Show("Available"); 
    } 
    else 
    { 
     MessageBox.Show("Not available"); 
    } 
} 
+1

Это работает только для одной сети. Если у вас несколько сетей, событие будет запущено только в том случае, если все сети отключены. Это не полезно в моем случае (см. Мое описание) – 2009-12-07 13:54:33

+0

OOPs Я пропустил это :( – Anuraj

0

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

0

Выполнение пинга определенно не самый чистый вариант, особенно если это веб-сервер. Некоторые хосты отключат ответ на трафик ICMP, поэтому вы можете выполнить ping, но не получить ответ. Как правильно обрабатывать исключение изящно, когда это происходит?

+1

Ну, на самом деле я не отправляю команду «ping», вместо этого я вызываю веб-сервис на своем веб-сервере. Это говорит мне, если мой WCF- Услуги все еще живы :) – 2009-12-07 14:31:04

8

Я попробовал ссылку, предложенную Webleeuw, но для этого кода также требуется от 4 до 10 секунд, чтобы уведомить меня, когда я подключаю или отсоединяю кабель. Теперь я хотел знать, был ли это только мой компьютер или установка, и я написал собственный класс Observer, который основан на NetworkInterface.GetAllNetworkInterfaces().

И: Он работает со скоростью молнии. Мое приложение реагирует так же быстро, как и лоток. Код далек от кода производства, это просто быстрый взлом. Но это то, что я буду опираться сейчас :)

using System; 
using System.Net.NetworkInformation; 
using Timer=System.Threading.Timer; 

namespace NetworkCheckApp 
{ 
public class NetworkStatusObserver 
{ 
    public event EventHandler<EventArgs> NetworkChanged; 

    private NetworkInterface[] oldInterfaces; 
    private Timer timer; 

    public void Start() 
    { 
     timer = new Timer(UpdateNetworkStatus, null, new TimeSpan(0, 0, 0, 0, 500), new TimeSpan(0, 0, 0, 0, 500)); 

     oldInterfaces = NetworkInterface.GetAllNetworkInterfaces(); 
    } 

    private void UpdateNetworkStatus(object o) 
    { 
     var newInterfaces = NetworkInterface.GetAllNetworkInterfaces(); 
     bool hasChanges = false; 
     if (newInterfaces.Length != oldInterfaces.Length) 
     { 
      hasChanges = true; 
     } 
     if (!hasChanges) 
     { 
      for (int i = 0; i < oldInterfaces.Length; i++) 
      { 
       if (oldInterfaces[i].Name != newInterfaces[i].Name || oldInterfaces[i].OperationalStatus != newInterfaces[i].OperationalStatus) 
       { 
        hasChanges = true; 
        break; 
       } 
      } 
     } 

     oldInterfaces = newInterfaces; 

     if (hasChanges) 
     { 
      RaiseNetworkChanged(); 
     } 
    } 

    private void RaiseNetworkChanged() 
    { 
     if (NetworkChanged != null) 
     { 
      NetworkChanged.Invoke(this, null); 
     } 
    } 
} 
} 
+1

Жаль, что мое редактирование не помогло вам, но приятное решение, которое вы предоставили себе :). Я мог бы использовать его сам в ближайшем будущем, поэтому спасибо за предоставление его здесь. – Webleeuw

2

Люди здесь уже сказали это, но есть различию между наличием и доступностью сети Интернет.
Вы можете иметь доступность сети между вашим сетевым интерфейсом и локальным маршрутизатором, но не имеете доступ к Интернету между вашим локальным маршрутизатором и вашим интернет-провайдером (ISP).
Есть еще одна проблема, что тестирование ping скажет вам о доступности интернета, но не о том, какой сетевой интерфейс предоставляет его, я думаю, что единственный способ - это принудительное пинг через один интерфейс, но это невозможно в окнах.

Смежные вопросы