Самый быстрый способ протестировать интернет-соединение
С# 2008 SP1
Я использую этот код для подключения к нашему клиентскому веб-сайту. Это для приложения софтфона. Перед тем, как пользователь делает вызов, софтфон должен проверить, есть ли активное интернет-соединение.
Итак, хочу, чтобы я сделал, используется класс httpWebRequest для подключения к веб-сайту наших клиентов. Если ответ в порядке, то подключение к Интернету может продолжаться.
Однако я заметил, что ответ слишком долго реагирует. Я не уверен, что это не очень эффективный способ тестирования.
Однако, когда я просматриваю их сайт, для загрузки страницы требуется меньше секунды. Но занимает слишком много времени, когда я использую класс HttpWebRequest
Таким образом, для этого требуются следующие условия:
Когда-то прокси-сервер будет использоваться в офисе клиента. Я не могу использовать класс TCPClient (не имеет свойства прокси).
Прокси не поддерживает SOCKS, поэтому не может использовать класс Sockets.
Мне нужно использовать свойство timeout. Поэтому нельзя использовать класс 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);
Ответы
Ответ 1
Попробуйте использовать P/Invoke для вызова InternetGetConnectedState. Это должно сказать вам, настроено ли соединение. Затем вы можете попробовать проверить конкретное соединение с вашим сервисом, используя InternetCheckConnection. Это (иногда) быстрее, чем подключение напрямую, но я бы проверил его, чтобы убедиться, что это лучше, чем просто полное соединение вверх.
Ответ 2
Что будет использовать программный телефон для его реального общения? Это происходит через HTTP/HTTPS на тот же веб-сайт? Если это так, это абсолютно правильный путь - следующий шаг - это выяснить, почему он так долго.
Является ли сетевое подключение определенно выше, чем вы можете запросить? Вы определенно не делаете никаких запросов заранее? Я спрашиваю, потому что я замечаю, что вы не избавляетесь от ответа - если это произойдет и в другом месте, вы можете обнаружить, что вы работаете против пула соединений, только предоставляя вам пару подключений к определенному серверу. Мораль всегда состоит в HttpWebResponse
в выражении using
. Конечно, это может не быть проблемой в вашем случае, но стоит попробовать.
Если ваше фактическое приложение будет подключаться в другом месте, тогда, когда ваш тест также должен быть проверен. В принципе, сделайте его как можно ближе к реальному.
Из интереса вы говорите, что это приложение "софтфон" - это на самом деле работает на телефоне какого-либо описания, используя компактную инфраструктуру или это настольное приложение?
Ответ 3
У меня была аналогичная ситуация, когда мы собирались сделать 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();
}
У меня нет фактического кода, который я использовал передо мной, но это должно поставить вас на общий путь.
Ответ 4
Вы можете ссылаться на пространство имен Microsoft.VisualBasic.Devices, чтобы использовать делегат NetworkAvailableEventHandler и класс Network. Я использую свойство Network.IsAvailable и Network.NetworkAvailabilityChanged, чтобы проверить, что сеть там (или затронута позже), а затем выполните HTTP GET на моем сервере, чтобы узнать, есть ли там сервер.
Это помогает сообщать о проблеме несколько более конкретно, вместо того, чтобы "не видеть сеть".
Ответ 5
Лучше всего добавить ссылку на Microsoft.VisualBasic и добавить оператор using Microsoft.VisualBasic.Device, тогда вы можете использовать следующую строку кода для проверки подключения к любой сети вообще.
public static bool isConnectedToNetwork {
get {
Network network = new Network();
return network.IsAvailable;
}
}
Ответ 6
request.GetResponse()
сам предоставит вам исключение, если имя хоста не может быть разрешено, поэтому, возможно, вы захотите поместить вокруг него try-catch, catch System.Net.WebException
и проверить его статус ошибки в Status
. Я не уверен, какие статусы точно не указывают на интернет; большинство ответов может быть также вызвано проблемами DNS или другими проблемами связи.