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

时间:2017-12-28 00:05:57

标签: c# events networking access

我编写的代码完美无缺,但我担心每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;

有人可以帮助我吗?

3 个答案:

答案 0 :(得分:2)

  

注意:注意原始解决方案

     

NetworkChange.NetworkAvailabilityChanged工作正常,但是   有一些警告:1)它没有告诉你你是否有   互联网访问,它只是告诉你是否至少有一个   非环回网络适配器工作,2)经常有额外的   出于各种原因安装的网络适配器离开系统   在"网络可用"国家,即使你的主要   互联网连接适配器已禁用/不可用 - 感谢 Peter Duniho

由于网络不仅仅是您的路由器或网卡,而且实际上您可以随时尝试连接到任何地方。最简单,最可靠的方法就是ping谷歌这样的知名来源,或者对你的某个互联网服务使用某种心跳。

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

因此IMCP ping到已知服务器(如Google)或OpenRead WebClient上的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(); } 是2种有效方法。这些呼叫相对而言并不昂贵,可以用于轻量级计时器或连续任务。

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

回答您的问题

  

但是我担心每2秒ping一次会占用太多资源   可以通过互联网连接制造一些问题。

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

  

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

Ping示例

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变体,它将返回一个   SM_CYMENU可以等待更适合IO绑定任务的Asynchronous programming模式

<强>资源

Ping.Send Method

Ping.SendAsync Method

WebClient.OpenRead Method

WebClient.OpenReadAsync Method

答案 1 :(得分: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解决方案也很出色。

答案 2 :(得分:-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

找到了它