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

Mar*_* DV 5 c# networking events

我编写的这段代码可以完美运行,但我担心每 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();
Run Code Online (Sandbox Code Playgroud)
    [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);
    }
Run Code Online (Sandbox Code Playgroud)

这两个事件并不是在所有场合都起作用(仅当IP或网卡发生变化时)

NetworkChange.NetworkAvailabilityChanged += NetworkChange_NetworkAvailabilityChanged
NetworkChange.NetworkAddressChanged += NetworkChange_NetworkAddressChanged;
Run Code Online (Sandbox Code Playgroud)

有人能帮我吗 ?

AAA*_*ddd 4

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

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

因为网络不仅仅是您的路由器或网卡,而且实际上是您随时尝试连接的每一跳。最简单、最可靠的方法就是 ping 一个众所周知的来源,例如谷歌,或者使用某种心跳来连接您的互联网服务之一。

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

因此,IMCP对已知服务器(如 Google)进行 ping 操作,或者OpenRead调用WebClient是两种有效的方法。这些调用相对来说并不昂贵,并且可以放入轻量级计时器或连续任务中。

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

回答你的问题

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

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

注意:只要确保您正在 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();
}
Run Code Online (Sandbox Code Playgroud)

连接示例

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
}
Run Code Online (Sandbox Code Playgroud)

注意:这两种方法都有一个async变体,该变体将返回 a Task并可以等待更适合 IO 绑定任务的异步编程模式

资源

Ping.发送方法

Ping.SendAsync 方法

WebClient.OpenRead 方法

WebClient.OpenReadAsync 方法