2 votes

C# Comment détecter la connexion / déconnexion d'Internet (avec un événement) ?

J'ai écrit ce code qui fonctionne parfaitement mais je crains que l'envoi d'un ping toutes les 2 secondes ne consomme trop de ressources ou ne crée des problèmes de connexion Internet.

        new Thread(() =>
        {
            if (CheckInternetConnection() == false)
            {
                Dispatcher.Invoke(new Action(delegate
                {
                    //internet access lost
                }));
            }
            else
            {
                Dispatcher.Invoke(new Action(delegate
                {
                    //internet access
                }));
            }

            Thread.Sleep(2000);
        }).Start();

    [DllImport("wininet.dll")]
    private extern static bool InternetGetConnectedState(out int Description, int ReservedValue);
    public static bool CheckInternetConnection()
    {
        int output = 0;
        return InternetGetConnectedState(out output, 0);
    }

Ce sont deux événements qui ne fonctionnent pas dans toutes les occasions (seulement quand l'IP ou la carte réseau change)

NetworkChange.NetworkAvailabilityChanged += NetworkChange_NetworkAvailabilityChanged
NetworkChange.NetworkAddressChanged += NetworkChange_NetworkAddressChanged;

Quelqu'un peut-il m'aider ?

2voto

TheGeneral Points 40470

Note : En réponse à votre solution originale

NetworkChange.NetworkAvailabilityChanged fonctionne bien, mais il y a un certain nombre d'inconvénients : 1) il ne vous indique pas si vous avez Internet, il vous dit seulement si au moins une carte réseau non rebouclée adaptateur réseau non bouclé qui fonctionne, et 2) il y a souvent des adaptateurs réseau adaptateurs réseau supplémentaires installés pour diverses raisons et qui laissent le système le système dans un état "réseau disponible", même lorsque votre adaptateur principal principal connecté à Internet est désactivé/non disponible - grâce à Peter Duniho

La mise en réseau ne se résume pas à votre routeur ou à votre carte réseau, mais concerne tous les points d'accès à l'endroit où vous essayez de vous connecter à tout moment. La méthode la plus simple et la plus fiable consiste à envoyer un ping à une source bien connue comme Google, ou à utiliser une sorte de battement de cœur vers l'un de vos services Internet.

La raison pour laquelle cette méthode est la seule fiable est que de nombreux problèmes de connectivité peuvent survenir entre vous et le monde extérieur. Même les grands fournisseurs de services peuvent tomber en panne.

Donc un IMCP ping vers un serveur connu comme Google, ou en appelant OpenRead sur un WebClient sont deux approches valables. Ces appels ne sont pas coûteux en comparaison et peuvent être intégrés dans une minuterie légère ou une tâche continue.

En ce qui concerne vos commentaires, vous pouvez probablement signaler un événement personnalisé pour indiquer la perte du réseau après un certain nombre d'échecs, par sécurité.

Pour répondre à votre question

Mais je crains que le ping toutes les 2 secondes consomme trop de ressources ou de puisse créer des problèmes de connexion à Internet.

Les deux méthodes sont très peu coûteuses en termes de CPU et de trafic réseau, les ressources utilisées doivent être minimales.

Note : Assurez-vous simplement que vous faites un ping ou que vous vous connectez à un serveur à haute disponibilité, cela permettre de telles manigances et ne pas simplement vous bloquer.

Exemple de ping

using System.Net.NetworkInformation;

// Implementation 
using (var ping = new Ping())
{
   var reply = ping.Send("www.google.com");
   if (reply != null && reply.Status != IPStatus.Success)
   {
      // Raise an event
      // you might want to check for consistent failures 
      // before signalling a the Internet is down
   }
}

// Or if you wanted to get fancy ping multiple sources
private async Task<List<PingReply>> PingAsync(List<string> listOfIPs)
{
    Ping pingSender = new Ping();
    var tasks = listOfIPs.Select(ip => pingSender.SendPingAsync(ip, 2000));
    var results = await Task.WhenAll(tasks);

    return results.ToList();
}

Exemple de connexion

using System.Net; 

// Implementation 
try
{
    using (WebClient client = new WebClient())
    {
       using (client.OpenRead("http://www.google.com/"))
       {
          // success
       }
    }
}
catch
{
    // Raise an event
    // you might want to check for consistent failures 
    // before signalling the Internet is down
}

Note : Ces deux méthodes ont un async qui renverra une Task et peut être attendue pour un Programmation asynchrone modèle mieux adapté aux tâches liées à l'IO

Ressources

Méthode Ping.Send

Méthode Ping.SendAsync

Méthode WebClient.OpenRead

Méthode WebClient.OpenReadAsync

0voto

Zarathos Points 3417

NetworkInterface.GetIsNetworkAvailable() n'est pas fiable... puisqu'il retournerait true même si tous les réseaux ne sont pas connectés à Internet. La meilleure approche pour vérifier la connectivité, à mon avis, est de faire un ping sur une ressource en ligne bien connue et rapide. Par exemple :

public static Boolean InternetAvailable()
{
    try
    {
        using (WebClient client = new WebClient())
        {
            using (client.OpenRead("http://www.google.com/"))
            {
                return true;
            }
        }
    }
    catch
    {
        return false;
    }
}

Quoi qu'il en soit, les deux événements auxquels vous souscrivez ne fonctionnent pas comme vous le pensez... en fait, ils vérifient l'état matériel de vos adaptateurs réseau... et non pas s'ils sont connectés à Internet ou non. Ils ont le même inconvénient que NetworkInterface.GetIsNetworkAvailable() . Continuez à vérifier la connectivité dans un fil séparé qui ping une source sûre et agissez en conséquence. Votre Interop La solution est également excellente.

-1voto

Andy Points 206

Faire un ping vers des ressources publiques entraîne des appels supplémentaires à votre application et ajoute une dépendance à ce site web ou à tout ce que vous utiliseriez dans la boucle.

Et si vous utilisiez cette méthode : NetworkInterface.GetIsNetworkAvailable() ? Serait-il suffisant pour les besoins de votre application ?

Je l'ai trouvé ici https://docs.microsoft.com/en-us/dotnet/api/system.net.networkinformation.networkinterface.getisnetworkavailable?view=netframework-4.7.1#System_Net_NetworkInformation_NetworkInterface_GetIsNetworkAvailable

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X