Самый быстрый способ проверить интернет-соединение - PullRequest
22 голосов
/ 09 мая 2009

C # 2008 SP1

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

Итак, я хочу использовать класс httpWebRequest для подключения к веб-сайту наших клиентов. Если ответ в порядке, то подключение к Интернету может продолжаться.

Однако я заметил, что ответ занимает слишком много времени, чтобы ответить. Я не уверен, что это не очень эффективный способ тестирования.

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

Итак, требования для этого:

Иногда прокси будет использоваться в офисе клиента. Я не могу использовать класс TCPClient (не имеет прокси-свойства).

Прокси-сервер не поддерживает SOCKS, поэтому не может использовать класс Sockets.

Мне нужно использовать свойство тайм-аута. Поэтому нельзя использовать класс WebClient. Это связано с тем, что программный телефон зависает до тех пор, пока не будет получен ответ. Так что таймаут через несколько секунд.

Так что я могу думать только о классе HttpWebRequest.

  HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://www.xxxxxxxxx.com");
            request.Timeout = 5000;
            request.Credentials = CredentialCache.DefaultNetworkCredentials;
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();

            if (response.StatusCode == HttpStatusCode.OK)
            {
                Console.WriteLine("IsSIPServerAvailable: " + response.StatusCode);
                isAvailable = true;
            }

======== Редактировать с помощью p \ Invoke ====

 [DllImport("wininet.dll", CharSet = CharSet.Auto)]
    private extern static bool InternetGetConnectedState(ref InternetConnectionState_e lpdwFlags, int dwReserved);

 [Flags]
    enum InternetConnectionState_e : int
    {
        INTERNET_CONNECTION_MODEM = 0x1,
        INTERNET_CONNECTION_LAN = 0x2,
        INTERNET_CONNECTION_PROXY = 0x4,
        INTERNET_RAS_INSTALLED = 0x10,
        INTERNET_CONNECTION_OFFLINE = 0x20,
        INTERNET_CONNECTION_CONFIGURED = 0x40
    }

 // In function for checking internet
 InternetConnectionState_e flags = 0;          
 bool isConnected = InternetGetConnectedState(ref flags, 0);

Ответы [ 6 ]

16 голосов
/ 09 мая 2009

Попробуйте использовать P / Invoke для вызова InternetGetConnectedState . Это должно сказать вам, есть ли у вас настроенное соединение. Затем вы можете попробовать проверить конкретное соединение с вашим сервисом, используя InternetCheckConnection . Это (иногда) быстрее, чем прямое подключение, но я бы проверил его, чтобы убедиться, что это лучше, чем просто выполнить полное подключение заранее.

11 голосов
/ 09 мая 2009

Какой софтфон собирается использовать для реального общения? Это происходит через HTTP / HTTPS на тот же веб-сайт? Если это так, то это абсолютно правильный путь - следующий шаг - выяснить, почему это занимает так много времени.

Установлено ли сетевое соединение, прежде чем вы можете запросить? Вы определенно не делаете какие-либо запросы заранее? Я спрашиваю, потому что замечаю, что вы не избавляетесь от ответа - если это происходит и в другом месте, вы можете обнаружить, что вы работаете с пулом соединений, давая вам только пару соединений с конкретным сервером. Мораль состоит в том, чтобы всегда ставить HttpWebResponse s в using утверждении. Конечно, это может не быть проблемой в вашем случае, но стоит попробовать.

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

Из интереса вы говорите, что это приложение "софтфона" - действительно ли оно работает на телефоне некоторого описания с использованием компактной платформы или это приложение для настольного компьютера?

6 голосов
/ 11 мая 2009

У меня была похожая ситуация, когда мы собирались сделать WCF-вызов клиенту, и это заняло бы слишком много времени, если бы клиент был недоступен (по какой-либо причине). Что я сделал, так это открыл необработанный сокет TCP по адресу клиента ... Это быстро завершается сбоем, если клиент не прослушивает порт (в вашем случае порт 80), и быстро выполняется, если они там есть.

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

Это выглядит примерно так ...

Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

    try
    {
         IAsyncResult result = socket.BeginConnect("www.xxxxxxxxx.com", 80, null, null );
         //I set it for 3 sec timeout, but if you are on an internal LAN you can probably 
         //drop that down a little because this should be instant if it is going to work
         bool success = result.AsyncWaitHandle.WaitOne( 3000, true );

         if ( !success )
         {
                throw new ApplicationException("Failed to connect server.");
         }

         // Success
         //... 
    }
    finally
    {
         //You should always close the socket!
         socket.Close();
    }

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

2 голосов
/ 10 мая 2009

Вы можете ссылаться на пространство имен Microsoft.VisualBasic.Devices, чтобы использовать делегат NetworkAvailableEventHandler и класс Network. Я использую свойство Network.IsAvailable и событие Network.NetworkAvailabilityChanged, чтобы проверить, есть ли сеть (или затронуто позже), а затем выполнить HTTP-GET для моего сервера, чтобы проверить, существует ли сервер.

Это помогает сообщить о проблеме немного более конкретно, вместо того, чтобы "не видеть сеть".

1 голос
/ 26 декабря 2012

Лучшим вариантом является добавление ссылки на Microsoft.VisualBasic и добавление оператора использования Microsoft.VisualBasic.Device, после чего вы можете использовать следующую строку кода для проверки подключения к любой сети вообще.

public static bool isConnectedToNetwork {
   get {
      Network network = new Network();
      return network.IsAvailable;
   }
}
0 голосов
/ 12 августа 2015

request.GetResponse() само по себе даст вам исключение, если имя хоста не может быть разрешено, так что вы можете захотеть попытаться это сделать, поймать System.Net.WebException и проверить его состояние ошибки в свойстве Status. Однако я не уверен, какие именно статусы будут указывать на отсутствие интернета; большинство ответов также может быть связано с DNS или другими проблемами с подключением.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...