C#如何检测互联网连接/断开连接(有事件)?

问题描述 投票:2回答:3

我编写的这段代码完美无缺,但我担心每2秒ping一次会消耗太多资源,或者会造成互联网连接问题。

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

这两个事件在所有场合都不起作用(仅在IP或网卡更改时)

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

有人能帮我吗 ?

c# events networking access
3个回答
2
投票

注意:关于您的原始解决方案

NetworkChange.NetworkAvailabilityChanged工作正常,但有一些警告:1)它不会告诉你是否有互联网访问,它只是告诉你是否至少有一个非环回网络适配器工作,2)通常有额外的网络由于各种原因安装的适配器使系统处于“网络可用”状态,即使您的主要连接互联网的适配器被禁用/不可用 - 感谢Peter Duniho

由于网络不仅仅是您的路由器或网卡,而且实际上每次跳到任何时候您都要尝试连接。最简单,最可靠的方法就是ping一个众所周知的来源,比如google,或者对你的某个互联网服务使用某种心跳。

这是唯一可靠的方法,原因是您和外界之间可能发生任何数量的连接问题。即使是主要服务提供商也可能会失败

所以IMCP ping到像谷歌这样的已知服务器,或者在OpenRead上调用WebClient是两种有效的方法。这些呼叫相对而言并不昂贵,可以用于轻量级计时器或连续任务。

至于您的评论,您可能会发出自定义事件的信号,表示在一定数量的安全失败后网络丢失

回答你的问题

但我担心每2秒ping一次会占用太多资源,或者会造成互联网连接问题。

这两种方法在CPU和网络流量方面都非常便宜,所使用的任何资源都应该非常少

注意:只需确保您正在ping或连接到具有高可用性的服务器,这将允许此类恶作剧而不仅仅阻止您

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

连接示例

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
}

注意:这两种方法都有一个async变体,它将返回一个Task,可以等待更适合IO绑定任务的Asynchronous programming模式

资源

Ping.Send Method

Ping.SendAsync Method

WebClient.OpenRead Method

WebClient.OpenReadAsync Method


0
投票

NetworkInterface.GetIsNetworkAvailable()是不可靠的......因为即使所有网络都没有连接到互联网,它也会返回true。在我看来,检查连接性的最佳方法是ping一个众所周知且快速的在线资源。例如:

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

无论如何,你订阅的那两个事件并不像你想象的那样工作......实际上他们会检查网络适配器的硬件状态......而不是它们是否连接到互联网。他们有与NetworkInterface.GetIsNetworkAvailable()相同的缺点。继续检查连接到一个单独的线程,该线程ping一个安全的源并相应地采取行动。你的Interop解决方案也很棒。


-1
投票

对公共资源执行ping操作会给您的应用带来额外的调用,并增加对该网站的依赖性或您在循环中使用的任何内容。

如果你使用这种方法怎么办:NetworkInterface.GetIsNetworkAvailable()?它是否适合您的应用程序的目的?

我发现它在这里https://docs.microsoft.com/en-us/dotnet/api/system.net.networkinformation.networkinterface.getisnetworkavailable?view=netframework-4.7.1#System_Net_NetworkInformation_NetworkInterface_GetIsNetworkAvailable

© www.soinside.com 2019 - 2024. All rights reserved.