2009-05-09 15 views
21

C# 2008 SP1La forma más rápida de probar la conexión a Internet

Estoy utilizando este código para conectarse al sitio web de nuestro cliente. Esto es para una aplicación de teléfono softphone. Antes de que el usuario haga una llamada, el softphone debe probar si hay una conexión a Internet activa.

Por lo tanto, quiero que he hecho se utiliza la clase httpWebRequest para conectarse al sitio web de nuestros clientes. Si la respuesta es correcta, entonces la conexión a Internet puede continuar.

Sin embargo, he notado que la respuesta tarda demasiado en responder. No estoy seguro de si esta no es una forma muy eficiente de probar.

Sin embargo, cuando navego a su sitio web, se tarda menos de un segundo en cargar la página. Pero lleva demasiado tiempo cuando se utiliza la clase HttpWebRequest

Así requisitos para esto son:

En algún momento de un proxy se utilizarán en la oficina del cliente. A No puedo usar la clase TCPClient (no tiene una propiedad de proxy).

El proxy no es compatible con SOCKS, por lo que no puede usar la clase Sockets.

Necesito usar una propiedad de tiempo de espera. Entonces no puedo usar la clase de WebClient. Esto se debe a que el softphone se congelará hasta que se devuelva una respuesta. Así que agote el tiempo después de unos segundos.

Así que el único en el que puedo pensar es en la clase 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; 
      } 

======== Editar usando p \ ==== Invocar

[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); 

Respuesta

16

Intente utilizar P/Invoke para llamar InternetGetConnectedState. Eso debería decirle si tiene o no una conexión configurada. Luego puede intentar verificar la conexión específica a su servicio usando InternetCheckConnection. Esto es (a veces) más rápido que conectar la conexión directamente, pero lo probaría para ver si es mejor que simplemente hacer una conexión completa por adelantado.

+3

La desventaja de eso (IMO) es que solo le dice si la computadora está conectada a "internet en general". Es solo un poco indicativo de si podrá acceder al servicio particular que busca. La mejor manera de hacerlo, IMO, es conectarse a ese mismo servicio. Por supuesto, eso no garantiza que seguirá siendo válido un segundo después, pero creo que es un mejor indicador si es posible. (En algunos casos no lo es, por ejemplo, si solo se conecta incurre en algún tipo de carga). –

+1

He editado mi código para la p/Invoke. Sin embargo, sí me dice si la LAN está conectada a mi computadora (enchufado o apagado). Sin embargo, no puede decirme si tengo una conexión a Internet activa (navegue por Internet). – ant2009

+0

@robUK: edité mi respuesta para incluir la llamada a InternetCheckConnection. Esa es otra P/Invoke que puede probar: debe decirle si esa URL específica está disponible, pero creo que es un poco más rápido que tratar de conectar una conexión usted mismo. –

11

¿Qué va a usar el softphone para su comunicación real? ¿Está pasando por HTTP/HTTPS al mismo sitio web? Si es así, es absolutamente el camino correcto, el siguiente paso es averiguar por qué tarda tanto.

¿La conexión de red está definitivamente activada antes de que usted pueda solicitarla? ¿Está definitivamente no haciendo alguna solicitud de antemano? Lo pregunto porque me doy cuenta de que no está deshaciéndose de la respuesta; si eso sucede también en otros lugares, es posible que encuentre que está corriendo contra el grupo de conexiones y que solo le da un par de conexiones a un servidor en particular. La moraleja es siempre ponga HttpWebResponse s en una declaración using. Por supuesto, puede ser que no sea el problema en su caso, pero vale la pena intentarlo.

Si su aplicación real se va a conectar en otro lugar, entonces es allí donde debería verificar también su prueba. Básicamente, hágalo lo más real posible.

Fuera de interés, que dicen que es una aplicación de "softphone" - se esta ejecutando realmente en un teléfono de algún tipo, utilizando el marco compacto, o se trata de una aplicación de escritorio?

+0

Hola. Es una ejecución de escritorio que puede ejecutarse en 2000, XP y Vista. Eso para la información en la declaración de uso. Olvidé eso. El servidor SIP está en el mismo servidor. Sin embargo, puedo conectarme usando el protocolo SIP y la transmisión mediante RTP. – ant2009

+0

Si en realidad se va a conectar con SIP más tarde, ¿por qué no conectarse con SIP para la prueba? ¿Hay alguna solicitud SIP no operativa que pueda hacer? –

+0

Estoy investigando algunas solicitudes SIP. También me gusta la opción P/invoke a continuación. Creo que voy a experimentar con ambas opciones. Gracias. – ant2009

2

Puede hacer referencia al espacio de nombres Microsoft.VisualBasic.Devices para usar el delegado NetworkAvailableEventHandler y la clase de red. Uso la propiedad Network.IsAvailable y el evento Network.NetworkAvailabilityChanged para verificar que la red esté allí (o se vea afectada posteriormente), y luego realizo un HTTP GET en mi servidor para ver si el servidor está allí.

Esto ayuda a informar el problema un poco más específicamente, en lugar de "no se puede ver la red".

6

Tuve una situación similar en la que íbamos a hacer una llamada WCF a un cliente y llevaría demasiado tiempo si el cliente no era accesible (por la razón que sea). Lo que hice fue abrir un socket TCP sin procesar a la dirección del cliente ... Esto falla rápidamente si el cliente no está escuchando en el puerto (en su caso, el puerto 80) y lo hace rápidamente si están allí.

Esto me dio la respuesta más rápida y precisa para determinar si sería capaz de comunicarme con el punto final que estaba tratando de alcanzar. El único inconveniente de esto es que tiene que administrar el tiempo de espera en el socket porque solo hay opciones para los tiempos de espera de envío y recepción que no se conectan.

Es algo parecido a esto ...

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(); 
    } 

que no tienen el código real que utilicé en frente de mí, pero esto se debe poner en el camino general.

+0

Hola, gracias por el código. En realidad, ya he probado la clase sockets. Sin embargo, el servidor proxy al que me tengo que conectar no admite el protocolo SOCKS.Si no fuera por el servidor proxy, esta sería una gran solución. – ant2009

+0

Lo siento, lo eché de menos en su pregunta ... –

+0

ONiel, gracias por esto. Estaba usando un TcpClient, y fue mucho más lento que este método. –

1

Una mejor opción es agregar referencia a Microsoft.VisualBasic y agregar una declaración de uso Microsoft.VisualBasic.Device luego puede usar la siguiente línea de código para verificar la conexión a cualquier red.

public static bool isConnectedToNetwork { 
    get { 
     Network network = new Network(); 
     return network.IsAvailable; 
    } 
} 
0

request.GetResponse() sí le dará una excepción si el nombre de host no se puede resolver, sin embargo, lo que podría querer poner un try-catch alrededor de eso, coger System.Net.WebException, y comprobar su estado de error en la propiedad Status. Sin embargo, no estoy seguro de qué estados indicarían exactamente que no hay internet; la mayoría de las respuestas podrían ser debidas a dns u otros problemas de conexión.

Cuestiones relacionadas