2009-12-07 9 views
12

Sé que no soy el primero en formular la pregunta: ¿Cómo puedo saber si mi aplicación está en línea o no? He encontrado esta publicación: StackOverflow. Quiero hacerlo con C# y .NET 3.5.Determinar si la conexión a Internet está disponible

La recomendación es hacer ping al recurso regularmente. No estoy muy contento con ese consejo. Preferiría detectar un cambio en la red y, a continuación, enviar un ping a mi servicio para verificar si está en línea.

.NET proporciona dos eventos para este propósito: NetworkChange.NetworkAvailabilityChanged NetworkChange.NetworkAddressChanged

El primer evento suena bien, pero se dispara sólo si la última tarjeta de red que está conectado se desconecta. Tengo varias tarjetas de red virtuales que han sido instaladas por VMWare y que están siempre en línea. El segundo evento funciona, pero entre conectar el cable de red y el evento, a menudo hay 5 segundos de tiempo de espera. El ícono de la bandeja de Windows reacciona de manera más o menos inmediata cuando estoy desconectando el cable. ¿Cuál es la mejor manera de ser tan rápido como este icono de bandeja?

Mi solución sería sondear NetworkInterface.GetAllNetworkInterfaces() cada 500 ms y para tirar mi propio evento en caso de que el estado de un adaptador de red cambia.

Tiene que haber una solución mejor :)

+0

¿Cómo planea detectar todos los cambios de red relevantes? Realmente no hay forma de que su aplicación note si algún enlace vital se pierde en el camino. –

+0

Ver mi edición para obtener nueva información sobre Iphlpapi.dll y NotifyAddrChange – Webleeuw

+0

¿En línea en qué sentido? Con un servidor? Si está en línea con un servidor, ¿por qué no simplemente envía un mensaje de estado cada 5 segundos para determinar si está en línea o no? –

Respuesta

0

ping de su recurso con regularidad es la única opción que le dará una notificación si el servicio se queda sin conexión, así como si el cliente se desconecta. Potencialmente, desea manejar ambas situaciones.

+0

Sí, lo sé. Para mí, el riesgo de que la red de un usuario específico no esté disponible es mucho mayor que el riesgo de que el servidor no esté disponible. Haremos ping, pero no de forma regular, sino solo cuando se inicie la aplicación y cuando se produzca un cambio en la red. Tal vez haremos ping con regularidad, pero luego no cada 500ms :) –

0

El icono de la bandeja de Windows está muy probablemente conectado a los controladores de la tarjeta de red, es decir, por debajo del nivel del sistema operativo, por lo que puede reaccionar tan rápido.

Como la tarjeta de red es solo uno de los muchos enlaces entre su cliente y el servicio al que accede en Internet, la única manera confiable de detectar si Internet está o no disponible es buscar algún servicio en Internet, de la misma manera que lo hace el ping. En la red TCP/IP, esto se conoce como keepalive, y muchos protocolos tendrán esto incorporado como una opción.

0

Acerca del pinging: dependiendo de cómo quiera interpretar los resultados, el ping no me parece hermético. ¿Qué sucede si el objetivo se agota de vez en cuando, mientras la conexión permanece activa? Todavía tengo que ver el servidor que nunca deja de responder a un ping.

Comprobando cada X millis si la interfaz de red aún está en línea (propiedad NetworkInterface.OperationalStatus) parece más confiable si me lo pregunta.

EDIT: This artículo trata con eventos de direcciones de red en un nivel inferior al de la clase System.Net.NetworkInformation.NetworkChange, o eso parece. En mi pc funciona muy rápido, así que espero que puedas usar esa solución.

+0

Gracias por el enlace. Lo he visto. Parece que se utiliza NetworkChange. Esto es útil, pero no estoy satisfecho con él, ya que es demasiado lento. –

+0

"Todavía no he visto el servidor que nunca deja de responder a un ping": es una mala suposición. Muchas redes lanzan paquetes ICMP. –

+0

@Roboto: No entiendo tu comentario, tal vez debido a una pequeña discrepancia de comunicación :). Con esa frase quise señalar el hecho de que el ping no es confiable porque un servidor podría eliminar uno o más paquetes de ping, incluso si está en línea. Más claramente: Todavía tengo que ver el servidor que responde siempre y siempre a cada ping que se envía. – Webleeuw

2

probar este usando networkChange clase

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

Esto funciona solo para una red. Si tiene varias redes, el evento solo se activará cuando todas las redes estén desconectadas. Esto no es útil en mi caso (ver mi descripción) –

+0

OOP Me perdí eso :( – Anuraj

0

Puede utilizar ping, pero también podía construir una simple llamada para devolver un "sí" si es en línea. De esta forma, usted sabe si el servidor está activo y si está ejecutando su código. También solo llamaría o haría ping cuando se necesita un recurso de red y no continuamente.

0

Realizar un ping definitivamente no es la opción más limpia, especialmente si se trata de un servidor web. Algunos hosts desactivarán la respuesta al tráfico ICMP, por lo que puede hacer ping pero no obtener una respuesta. ¿Qué tal si manejamos la excepción con gracia cuando ocurre?

+1

Bueno, en realidad no estoy enviando un comando "ping". En su lugar, estoy llamando a un servicio web en mi servidor web. Esto me dice si mi WCF- Los servicios todavía están vivos :) –

8

Probé el enlace que Webleeuw sugirió, pero ese código también necesita entre 4 y 10 segundos para notificarme cuando enchufo o desenchufo el cable. Ahora, quería saber si era solo mi computadora o instalación y escribí mi propia clase Observer que está basada en NetworkInterface.GetAllNetworkInterfaces().

Y: Funciona a la velocidad del rayo. Mi aplicación reacciona ahora tan rápido como la bandeja. El código está lejos del código de producción, es solo un truco rápido. Pero esto es lo que voy a aprovechar ahora :)

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

Una lástima que mi edición no haya sido de utilidad, pero es una buena solución que te has proporcionado :). Podría usarlo yo mismo en el (próximo) futuro, así que gracias por proporcionarlo aquí. – Webleeuw

2

La gente aquí ya lo dijeron, pero hay una diference entre la disponibilidad de la red y la disponibilidad de Internet.
Puede tener disponibilidad de red entre su interfaz de red y el enrutador local, pero no tiene disponibilidad de Internet entre su enrutador local y su proveedor de servicios de Internet (ISP).
Hay otro problema que las pruebas de ping le informarán sobre la disponibilidad de Internet, pero no sobre qué interfaz de red lo está proporcionando, creo que la única forma es forzar el ping a través de una interfaz, pero no es posible en Windows.

Cuestiones relacionadas