【问题标题】:What is the best way to check for Internet connectivity using .NET?使用 .NET 检查 Internet 连接的最佳方法是什么?
【发布时间】:2011-01-03 03:51:50
【问题描述】:

在 .NET 中检查 Internet 连接的最快和最有效的方法是什么?

【问题讨论】:

  • 如果用户有互联网连接。如果用户可以连接到互联网。为了发送电子邮件日志。
  • 发送电子邮件即可。如果用户未连接,您可能会收到某种异常(无论如何您可能都必须处理)。
  • 另外,请注意,无法检查用户是否连接到互联网;你所能知道的就是他们是否过去曾联系过。假设您有一个方法:“bool c = IsConnected(); if (c) { DoSomething(); }” -- 在调用 IsConnected 和 DoSomething 之间,无线网络路由器可能已被拔掉。 IsConnected 确实应该称为 WasRecentlyConnected。
  • Windows NLM API 应该是最好的。 stackoverflow.com/questions/5405895/…
  • 在不了解您的用例的情况下,您可能更谨慎地担心防火墙不会阻止对您关心的服务器的访问,而不是对整个 Internet 的访问。

标签: c# .net internet-connection


【解决方案1】:
public static bool CheckForInternetConnection(int timeoutMs = 10000, string url = null)
{
    try
    {
        url ??= CultureInfo.InstalledUICulture switch
        {
            { Name: var n } when n.StartsWith("fa") => // Iran
                "http://www.aparat.com",
            { Name: var n } when n.StartsWith("zh") => // China
                "http://www.baidu.com",
            _ =>
                "http://www.gstatic.com/generate_204",
        };

        var request = (HttpWebRequest)WebRequest.Create(url);
        request.KeepAlive = false;
        request.Timeout = timeoutMs;
        using (var response = (HttpWebResponse)request.GetResponse())
            return true;
    }
    catch
    {
        return false;
    }
}

【讨论】:

  • 这可能比 ping Google 更好,因为我认为我们无法保证 Google 会继续响应 ping。另一方面,我无法想象 www.google.com 不返回一些 HTML 的世界:)
  • @Daniel:一方面是的,但另一方面,实际上下载网站有点开销 imo
  • 无论如何,没有理由将 4KB 拉回来 - 只需使用 client.OpenRead(url) 代替。如果它没有抛出异常,那么它就能够连接。
  • 其实效率不高。如果没有互联网,使用它会使我的程序启动超过 1 分钟。可能是由于尝试解析 DNS。 Pinging 8.8.8.8 (google dns) 将其更改为 3 秒。
  • @DanielVassallo I cannot image a world where www.google.com does not return some HTML 在中国例如...
【解决方案2】:

你绝对没有办法可靠地检查是否有互联网连接(我假设你的意思是访问互联网)。

但是,您可以请求几乎从不离线的资源,例如 ping google.com 或类似的东西。我认为这将是有效的。

try { 
    Ping myPing = new Ping();
    String host = "google.com";
    byte[] buffer = new byte[32];
    int timeout = 1000;
    PingOptions pingOptions = new PingOptions();
    PingReply reply = myPing.Send(host, timeout, buffer, pingOptions);
    return (reply.Status == IPStatus.Success);
}
catch (Exception) {
    return false;
}

【讨论】:

  • +1 "绝对没有办法可靠地检查是否有互联网连接"
  • 所有这一切都是在您 ping 时检查 google 是否已启动。如果在您成功 ping 互联网后的下一瞬间出现故障,那会怎样?在做之前检查是没有意义的。
  • 这与我回答的主要陈述有何矛盾?
  • 使用“google.com”需要更多时间,因为它需要解决。相反,直接使用 IP ping 会更快。 ping 到 Google 公共 DNS IP 地址(8.8.8.88.8.4.4)对我来说很好。
  • 我想重申一点,Beware - many schools and offices block the ping protocol. 如果您将这种方法用于客户将使用的应用程序,我建议您不要使用这种检查互联网的方法
【解决方案3】:

无需检查,只需执行操作(Web 请求、邮件、ftp 等)并为请求失败做好准备,即使检查成功,您也必须这样做。

考虑以下几点:

1 - check, and it is OK
2 - start to perform action 
3 - network goes down
4 - action fails
5 - lot of good your check did

如果网络出现故障,您的操作将像 ping 等一样迅速失败。

1 - start to perform action
2 - if the net is down(or goes down) the action will fail

【讨论】:

  • 对!去做吧——但要为所有结果做好准备。
  • 考虑以下几点:如果网络中断了 x 时间(例如跟踪日志、路由器重置),您需要 做一些事情
  • 不是 OP,但我想这样做的原因是在 Internet 连接不可用时避免默认的 100 秒超时。 HTTP 请求是在后台线程上完成的,因此 UI 线程不会被阻塞,但我的应用程序无法退出,直到后台线程从 HTTP 请求返回并终止。如果我知道 Internet 连接已断开,我宁愿完全避免请求,而不是尝试找到一些“快乐的中等”超时值。
  • 我的意思是,我们无法解释远程服务何时可用/不可用。另外,那些不响应 ping 的网站呢?
  • 当然,了解“客户端无法访问您的特定 Web 服务”和“客户端根本无法访问 Internet”之间的区别很有用。我之所以关注这 10 年,是因为我希望本地应用程序在启动时具有不同的行为,如果我的网络服务关闭,或者它无法访问网络;如果你不知道发生了什么,你应该如何“做好准备”?
【解决方案4】:

NetworkInterface.GetIsNetworkAvailable 非常不可靠。只要有一些 VMware 或其他 LAN 连接,它就会返回错误的结果。 另外关于 Dns.GetHostEntry 方法,我只是担心测试 URL 是否可能在我的应用程序要部署的环境中被阻止。

所以我发现的另一种方法是使用InternetGetConnectedState 方法。 我的代码是

[System.Runtime.InteropServices.DllImport("wininet.dll")]
private extern static bool InternetGetConnectedState(out int Description, int ReservedValue);

public static bool CheckNet()
{
     int desc;
     return InternetGetConnectedState(out desc, 0);         
}

【讨论】:

  • 在测试过程中,我发现安装VMWare播放器时InternetGetConnectedState返回true(互联网断开)。必须在控制面板\网络和 Internet\网络连接(VMNet1 和 VMNet8)中禁用它。
  • 对我来说最好的方法,在那之后我仍然检查我的服务连接,然后开始例程......我只是想避免异常。
  • 这段代码只检查网线是否插入。
  • 此代码不可移植到 Linux、MacOS。
  • 嗨@weePee,如果你正在尝试使用 .net core,那么请记住这篇文章是 2014 年的 pre .net core 时代
【解决方案5】:

通过 ping Google 测试互联网连接:

new Ping().Send("www.google.com.mx").Status == IPStatus.Success

【讨论】:

  • 附上这个答案的描述将有利于更多的人,而不仅仅是问题的原作者。
  • 当心 - 许多学校和办公室会阻止 ping 协议。傻,我知道。
  • 我找不到 ping 类。请你帮助我好吗。我正在开发 UWP,但通过网络信息的其他方式不起作用
【解决方案6】:

ping google.com 引入了 DNS 解析依赖项。 ping 8.8.8.8 很好,但谷歌离我还有几跳。我需要做的就是 ping 互联网上离我最近的东西。

我可以使用Ping 的 TTL 功能来 ping #1,然后 hop #2,等等,直到我从可路由地址上的某处得到回复;如果该节点位于可路由地址上,则它位于 Internet 上。对于我们大多数人来说,第 1 跳将是我们的本地网关/路由器,而第 2 跳将是我们光纤连接另一端的第一个点或其他任何东西。

此代码对我有用,并且比此线程中的其他一些建议响应更快,因为它正在 ping 互联网上离我最近的任何内容。


using System.Diagnostics;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Threading.Tasks;
    
public static async Task<bool> IsConnectedToInternetAsync()
{
    const int maxHops = 30;
    const string someFarAwayIpAddress = "8.8.8.8";
    
    // Keep pinging further along the line from here to google 
    // until we find a response that is from a routable address
    for (int ttl = 1; ttl <= maxHops; ttl++)
    {
        var options = new PingOptions(ttl, true);
        byte[] buffer = new byte[32];
        PingReply reply;
        try
        {
            using (var pinger = new Ping())
            {
                reply = await pinger.SendPingAsync(someFarAwayIpAddress, 10000, buffer, options);
            }
        }
        catch (PingException pingex)
        {
            Debug.Print($"Ping exception (probably due to no network connection or recent change in network conditions), hence not connected to internet. Message: {pingex.Message}");
            return false;
        }
    
        string address = reply.Address?.ToString() ?? null;
        Debug.Print($"Hop #{ttl} is {address}, {reply.Status}");
    
        if (reply.Status != IPStatus.TtlExpired && reply.Status != IPStatus.Success)
        {
            Debug.Print($"Hop #{ttl} is {reply.Status}, hence we are not connected.");
            return false;
        }
    
        if (IsRoutableAddress(reply.Address))
        {
            Debug.Print("That's routable, so we must be connected to the internet.");
            return true;
        }
    }
    
    return false;
}
    
private static bool IsRoutableAddress(IPAddress addr)
{
    if (addr == null)
    {
        return false;
    }
    else if (addr.AddressFamily == AddressFamily.InterNetworkV6)
    {
        return !addr.IsIPv6LinkLocal && !addr.IsIPv6SiteLocal;
    }
    else // IPv4
    {
        byte[] bytes = addr.GetAddressBytes();
        if (bytes[0] == 10)
        {   // Class A network
            return false;
        }
        else if (bytes[0] == 172 && bytes[1] >= 16 && bytes[1] <= 31)
        {   // Class B network
            return false;
        }
        else if (bytes[0] == 192 && bytes[1] == 168)
        {   // Class C network
            return false;
        }
        else
        {   // None of the above, so must be routable
            return true;
        }
    }
}

【讨论】:

  • 这是一种有趣的方法,与其他答案完全不同! (+1)
【解决方案7】:

我不同意有人说:“在执行任务之前检查连接有什么意义,因为在检查之后连接可能会立即丢失”。 当然,我们作为开发人员承担的许多编程任务都存在一定程度的不确定性,但将不确定性降低到可接受的水平是挑战的一部分。

我最近在制作一个应用程序时遇到了这个问题,该应用程序包括一个链接到在线磁贴服务器的映射功能。如果发现缺少 Internet 连接,将禁用此功能。

此页面上的一些响应非常好,但确实导致了很多性能问题,例如挂起,主要是在没有连接的情况下。

在其中一些答案和我的同事的帮助下,这是我最终使用的解决方案:

         // Insert this where check is required, in my case program start
         ThreadPool.QueueUserWorkItem(CheckInternetConnectivity);
    }

    void CheckInternetConnectivity(object state)
    {
        if (System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable())
        {
            using (WebClient webClient = new WebClient())
            {
                webClient.CachePolicy = new System.Net.Cache.RequestCachePolicy(System.Net.Cache.RequestCacheLevel.BypassCache);
                webClient.Proxy = null;
                webClient.OpenReadCompleted += webClient_OpenReadCompleted;
                webClient.OpenReadAsync(new Uri("<url of choice here>"));
            }
        }
    }

    volatile bool internetAvailable = false; // boolean used elsewhere in code

    void webClient_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
    {
        if (e.Error == null)
        {
            internetAvailable = true;
            Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
            {
                // UI changes made here
            }));
        }
    }

【讨论】:

    【解决方案8】:

    我已经看到了上面列出的所有选项,检查互联网是否可用的唯一可行选项是“Ping”选项。 导入[DllImport("Wininet.dll")]System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces()NetworkInterface 类的任何其他变体都不能很好地检测网络的可用性。这些方法只检查网络电缆是否插入。

    “Ping 选项”

    if(连接可用)返回true

    if(连接不可用,网线插上)返回false

    if(网线未插好)Throws an exception

    网络接口

    if(互联网可用)返回True

    if(Internet 不可用且网线已插入) 返回True

    if(网线未插入)返回false

    [DllImport("Wininet.dll")]

    if(互联网可用)返回True

    if(Internet 不可用且网线已插入) 返回True

    if(网线未插入)返回false

    所以在[DllImport("Wininet.dll")]NetworkInterface 的情况下,无法知道互联网连接是否可用。

    【讨论】:

    • 这不是真的,我导入了Wininet.dll,插上网线,得到了正确的结果,场景互联网不可用。
    【解决方案9】:

    不能解决在检查和运行代码之间网络中断的问题 但相当可靠

    public static bool IsAvailableNetworkActive()
    {
        // only recognizes changes related to Internet adapters
        if (System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable())
        {
            // however, this will include all adapters -- filter by opstatus and activity
            NetworkInterface[] interfaces = System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces();
            return (from face in interfaces
                    where face.OperationalStatus == OperationalStatus.Up
                    where (face.NetworkInterfaceType != NetworkInterfaceType.Tunnel) && (face.NetworkInterfaceType != NetworkInterfaceType.Loopback)
                    select face.GetIPv4Statistics()).Any(statistics => (statistics.BytesReceived > 0) && (statistics.BytesSent > 0));
        }
    
        return false;
    }
    

    【讨论】:

    • 好主意,但就像你说的那样可能并不完美。您也可以缓存发送/接收的字节以供将来检查。不过仍然不完美。
    • 此代码无效,请更正。它只检查网线是否插入。
    • (根据 MSDN):“如果任何网络接口被标记为“启动”并且不是环回或隧道接口,则认为网络连接可用。除了检查BytesSentBytesReceived 之外,您基本上只是复制了GetIsNetworkAvailable 中已有的功能。
    【解决方案10】:

    Here's在Android中是如何实现的。

    作为概念证明,我将这段代码翻译成 C#:

    var request = (HttpWebRequest)WebRequest.Create("http://g.cn/generate_204");
    request.UserAgent = "Android";
    request.KeepAlive = false;
    request.Timeout = 1500;
    
    using (var response = (HttpWebResponse)request.GetResponse())
    {
        if (response.ContentLength == 0 && response.StatusCode == HttpStatusCode.NoContent)
        {
            //Connection to internet available
        }
        else
        {
            //Connection to internet not available
        }
    }
    

    【讨论】:

      【解决方案11】:
      private bool ping()
      {
          System.Net.NetworkInformation.Ping pingSender = new System.Net.NetworkInformation.Ping();
          System.Net.NetworkInformation.PingReply reply = pingSender.Send(address);
          if (reply.Status == System.Net.NetworkInformation.IPStatus.Success)
          {                
              return true;
          }
          else
          {                
              return false;
          }
      }
      

      【讨论】:

        【解决方案12】:

        尝试通过捕获异常来避免测试连接。因为我们真的期望有时我们可能会失去网络连接。

         if (NetworkInterface.GetIsNetworkAvailable() &&
             new Ping().Send(new IPAddress(new byte[] { 8, 8, 8, 8 }),2000).Status == IPStatus.Success)
         //is online
         else
         //is offline
        

        【讨论】:

        • 网络接口从何而来?编辑:我找到它:System.Net.NetworkInformation
        【解决方案13】:

        我不认为这是不可能的,只是不简单。

        我已经构建了这样的东西,是的,它并不完美,但第一步是必不可少的:检查是否有任何网络连接。 Windows Api 做得不好,为什么不做得更好呢?

        bool NetworkIsAvailable()
        {
            var all = System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces();
            foreach (var item in all)
            {
                if (item.NetworkInterfaceType == NetworkInterfaceType.Loopback)
                    continue;
                if (item.Name.ToLower().Contains("virtual") || item.Description.ToLower().Contains("virtual"))
                    continue; //Exclude virtual networks set up by VMWare and others
                if (item.OperationalStatus == OperationalStatus.Up)
                {
                    return true;
                }
            }
        
            return false;
        }
        

        这很简单,但确实有助于提高检查质量,尤其是当您要检查各种代理配置时。

        所以:

        • 检查是否有网络连接(让它变得非常好,甚至可能在出现误报时将日志发送回开发人员以改进 NetworkIsAvailable 功能)
        • HTTP Ping
        • (循环使用每个 HTTP Ping 的代理配置)

        【讨论】:

        • @hackerman 这是不明显的第一步。第二步,如果返回 true,编码人员可以快速 ping 到他们自己的服务器。重要的是,这为有缺陷的 windows api 方法提供了一种替代方法。剩下的就是细节了。
        • 伪造。如果没有网络接口,肯定没有互联网。用户界面可以立即更新,没有延迟,无需进一步检查其他主机。
        【解决方案14】:

        另一个选项是可用于 Vista 和 Windows 7 的 Network List Manager API。MSDN 文章 here。文章中有一个下载代码示例的链接,您可以这样做:

        AppNetworkListUser nlmUser = new AppNetworkListUser();
        Console.WriteLine("Is the machine connected to internet? " + nlmUser.NLM.IsConnectedToInternet.ToString());
        

        请务必从 COM 选项卡中添加对 Network List 1.0 类型库的引用...这将显示为 NETWORKLIST。

        【讨论】:

        • eeeeww。在 .NET 中使用 COM 地狱?
        • @jgauffin 你能解释一下为什么在 .NET 中应该避免使用 COM 吗?与我发现的其他解决方案相比,COM 解决方案似乎运行良好。
        【解决方案15】:

        简介

        在某些情况下,您需要在 Windows 应用程序中使用 C# 代码检查 Internet 是否可用。可能是使用互联网以 Windows 形式下载或上传文件,或者从远程位置的数据库中获取一些数据,在这些情况下,互联网检查是强制性的。

        有一些方法可以使用 C# 从后面的代码中检查 Internet 可用性。此处解释了所有这些方式,包括它们的局限性。

        1. InternetGetConnectedState(wininet)

        'wininet' API 可用于检查本地系统是否有活动的互联网连接。用于此的命名空间是“System.Runtime.InteropServices”并使用 DllImport 导入 dll“wininet.dll”。在此之后创建一个带有 extern static 的布尔变量,其函数名称为 InternetGetConnectedState,其中包含两个参数 description 和 reservedValue,如示例所示。

        注意:extern 修饰符用于声明在外部实现的方法。当您使用互操作服务调用非托管代码时,extern 修饰符的一个常见用途是与 DllImport 属性一起使用。在这种情况下,该方法也必须声明为静态。

        接下来创建一个名为“IsInternetAvailable”作为布尔值的方法。这 上面的函数将在这个返回互联网的方法中使用 本地系统状态

        [DllImport("wininet.dll")]
        private extern static bool InternetGetConnectedState(out int description, int reservedValue);
        public static bool IsInternetAvailable()
        {
            try
            {
                int description;
                return InternetGetConnectedState(out description, 0);
            }
            catch (Exception ex)
            {
                return false;
            }
        }
        
        1. GetIsNetworkAvailable

        以下示例使用 GetIsNetworkAvailable 方法来确定网络连接是否可用。

        if (System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable())
        {
            System.Windows.MessageBox.Show("This computer is connected to the internet");
        }
        else
        {
            System.Windows.MessageBox.Show("This computer is not connected to the internet");
        }
        

        备注(根据 MSDN):如果任何网络接口被标记为“up”并且不是环回或隧道接口,则认为网络连接可用。

        在很多情况下,设备或计算机未连接到有用的网络,但仍被认为可用,GetIsNetworkAvailable 将返回 true。例如,如果运行应用程序的设备连接到需要代理的无线网络,但未设置代理,则 GetIsNetworkAvailable 将返回 true。 GetIsNetworkAvailable 何时返回 true 的另一个示例是,如果应用程序在连接到集线器或路由器的计算机上运行,​​而该集线器或路由器已失去上游连接。

        1. Ping 网络上的主机名

        Ping 和 PingReply 类允许应用程序通过从主机获取回复来确定远程计算机是否可通过网络访问。这些类在 System.Net.NetworkInformation 命名空间中可用。以下示例显示了如何 ping 主机。

        protected bool CheckConnectivity(string ipAddress)
        {
            bool connectionExists = false;
            try
            {
                System.Net.NetworkInformation.Ping pingSender = new System.Net.NetworkInformation.Ping();
                System.Net.NetworkInformation.PingOptions options = new System.Net.NetworkInformation.PingOptions();
                options.DontFragment = true;
                if (!string.IsNullOrEmpty(ipAddress))
                {
                    System.Net.NetworkInformation.PingReply reply = pingSender.Send(ipAddress);
                    connectionExists = reply.Status == 
        System.Net.NetworkInformation.IPStatus.Success ? true : false;
                }
            }
            catch (PingException ex)
            {
                Logger.LogException(ex.Message, ex);
            }
            return connectionExists;
        }
        

        备注(根据 MSDN):应用程序使用 Ping 类来检测远程计算机是否可访问。网络拓扑可以确定 Ping 是否可以成功联系到远程主机。代理、网络地址转换 (NAT) 设备或防火墙的存在和配置会阻止 Ping 成功。 Ping 成功仅表明网络上可以访问远程主机;无法保证远程主机上存在更高级别的服务(例如 Web 服务器)。

        欢迎评论/建议。编码快乐......!

        【讨论】:

          【解决方案16】:

          accepted answer 快速成功,但在没有连接时失败很慢。所以我想建立一个健壮的连接检查,它会更快地失败。

          据说并非所有环境都支持 Pinging,所以我从接受的答案开始,并从 here 添加了一个具有自定义超时的 WebClient。您可以选择任何超时,但通过 wifi 连接时,3 秒对我有用。我尝试添加一个快速迭代(1 秒),如果第一个迭代失败,则添加一个慢速迭代(3 秒)。但这没有任何意义,因为两次迭代总是会失败(未连接时)或总是成功(连接时)。

          我正在连接 AWS,因为我想在连接测试通过时上传文件。

          public static class AwsHelpers
          {
              public static bool GetCanConnectToAws()
              {
                  try
                  {
                      using (var client = new WebClientWithShortTimeout())
                      using (client.OpenRead("https://aws.amazon.com"))
                          return true;
                  }
                  catch
                  {
                      return false;
                  }
              }
          }
          
          public class WebClientWithShortTimeout: WebClient
          {
              protected override WebRequest GetWebRequest(Uri uri)
              {
                  var webRequest = base.GetWebRequest(uri);
                  webRequest.Timeout = 5000;
                  return webRequest;
              }
          }
          

          【讨论】:

            【解决方案17】:

            【讨论】:

              【解决方案18】:

              我个人认为Anton and moffeltje 的答案最好,但我添加了一个检查以排除VMWare 和其他人设置的虚拟网络。

              public static bool IsAvailableNetworkActive()
              {
                  // only recognizes changes related to Internet adapters
                  if (!System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable()) return false;
              
                  // however, this will include all adapters -- filter by opstatus and activity
                  NetworkInterface[] interfaces = System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces();
                  return (from face in interfaces
                          where face.OperationalStatus == OperationalStatus.Up
                          where (face.NetworkInterfaceType != NetworkInterfaceType.Tunnel) && (face.NetworkInterfaceType != NetworkInterfaceType.Loopback)
                          where (!(face.Name.ToLower().Contains("virtual") || face.Description.ToLower().Contains("virtual")))
                          select face.GetIPv4Statistics()).Any(statistics => (statistics.BytesReceived > 0) && (statistics.BytesSent > 0));
              }
              

              【讨论】:

              • GetIsNetworkAvailable() 文档中的仅供参考:如果任何网络接口被标记为“up”并且不是环回或隧道接口,则认为网络连接可用。我不知道 virtual 是否总是在接口的名称或描述中。这是标准吗?
              【解决方案19】:
              public static bool Isconnected = false;
              
              public static bool CheckForInternetConnection()
              {
                  try
                  {
                      Ping myPing = new Ping();
                      String host = "google.com";
                      byte[] buffer = new byte[32];
                      int timeout = 1000;
                      PingOptions pingOptions = new PingOptions();
                      PingReply reply = myPing.Send(host, timeout, buffer, pingOptions);
                      if (reply.Status == IPStatus.Success)
                      {
                          return true;
                      }
                      else if (reply.Status == IPStatus.TimedOut)
                      {
                          return Isconnected;
                      }
                      else
                      {
                          return false;
                      }
                  }
                  catch (Exception)
                  {
                      return false;
                  }
              }
              
              public static void CheckConnection()
              {
                  if (CheckForInternetConnection())
                  {
                      Isconnected = true;
                  }
                  else
                  {
                      Isconnected = false;
                  }
              }
              

              【讨论】:

              • 请评论您的答案。不允许只有代码的答案。
              • 这很不言自明,为了治安而治安?
              【解决方案20】:
              bool bb = System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable();
              
              if (bb == true)
                  MessageBox.Show("Internet connections are available");
              else
                  MessageBox.Show("Internet connections are not available");
              

              【讨论】:

              • 您能否添加与此速度相关的信息,以及这比发布的其他解决方案如何更好。这将有助于您全面解决问题。
              • 这个选项的问题是bb即使在网络没有连接到互联网时仍然是真的。
              • 虽然这确实不能直接回答问题,但我认为在尝试 ping Google 等之前使用 GetIsNetworkAvailable 作为预检查仍然很有用。
              • 此代码不能说明 Internet 连接是否可用。如果您在没有互联网的情况下插入网线,它将返回 true。
              【解决方案21】:

              ping 的多线程版本:

                using System;
                using System.Collections.Generic;
                using System.Diagnostics;
                using System.Net.NetworkInformation;
                using System.Threading;
              
              
                namespace OnlineCheck
                {
                    class Program
                    {
              
                        static bool isOnline = false;
              
                        static void Main(string[] args)
                        {
                            List<string> ipList = new List<string> {
                                "1.1.1.1", // Bad ip
                                "2.2.2.2",
                                "4.2.2.2",
                                "8.8.8.8",
                                "9.9.9.9",
                                "208.67.222.222",
                                "139.130.4.5"
                                };
              
                            int timeOut = 1000 * 5; // Seconds
              
              
                            List<Thread> threadList = new List<Thread>();
              
                            foreach (string ip in ipList)
                            {
              
                                Thread threadTest = new Thread(() => IsOnline(ip));
                                threadList.Add(threadTest);
                                threadTest.Start();
                            }
              
                            Stopwatch stopwatch = Stopwatch.StartNew();
              
                            while (!isOnline && stopwatch.ElapsedMilliseconds <= timeOut)
                            {
                                 Thread.Sleep(10); // Cooldown the CPU
                            }
              
                            foreach (Thread thread in threadList)
                            { 
                                thread.Abort(); // We love threads, don't we?
                            }
              
              
                            Console.WriteLine("Am I online: " + isOnline.ToYesNo());
                            Console.ReadKey();
                        }
              
                        static bool Ping(string host, int timeout = 3000, int buffer = 32)
                        {
                            bool result = false;
              
                            try
                            {
                                Ping ping = new Ping();                
                                byte[] byteBuffer = new byte[buffer];                
                                PingOptions options = new PingOptions();
                                PingReply reply = ping.Send(host, timeout, byteBuffer, options);
                                result = (reply.Status == IPStatus.Success);
                            }
                            catch (Exception ex)
                            {
              
                            }
              
                            return result;
                        }
              
                        static void IsOnline(string host)
                        {
                            isOnline =  Ping(host) || isOnline;
                        }
                    }
              
                    public static class BooleanExtensions
                    {
                        public static string ToYesNo(this bool value)
                        {
                            return value ? "Yes" : "No";
                        }
                    }
                }
              

              【讨论】:

                【解决方案22】:

                使用NetworkMonitor 监控网络状态和互联网连接。

                示例:

                namespace AmRoNetworkMonitor.Demo
                {
                    using System;
                
                    internal class Program
                    {
                        private static void Main()
                        {
                            NetworkMonitor.StateChanged += NetworkMonitor_StateChanged;
                            NetworkMonitor.StartMonitor();
                
                            Console.WriteLine("Press any key to stop monitoring.");
                            Console.ReadKey();
                            NetworkMonitor.StopMonitor();
                
                            Console.WriteLine("Press any key to close program.");
                            Console.ReadKey();
                        }
                
                        private static void NetworkMonitor_StateChanged(object sender, StateChangeEventArgs e)
                        {
                            Console.WriteLine(e.IsAvailable ? "Is Available" : "Is Not Available");
                        }
                    }
                }
                

                【讨论】:

                • 好主意,但检查网络可用性,而不是互联网可用性
                • 这个类还检查互联网的可用性:SourceCode
                • 问题是,我试过了,但只有在没有可用网络时才会触发
                【解决方案23】:

                对于我的应用程序,我们还通过下载小文件进行测试。

                string remoteUri = "https://www.microsoft.com/favicon.ico"
                
                WebClient myWebClient = new WebClient();
                
                try
                {
                    byte[] myDataBuffer = myWebClient.DownloadData (remoteUri);
                    if(myDataBuffer.length > 0) // Or add more validate. eg. checksum
                    {
                        return true;
                    }
                }
                catch
                {
                    return false;
                }
                

                还有。一些 ISP 可能会使用中间服务器来缓存文件。添加随机未使用的参数,例如。 https://www.microsoft.com/favicon.ico?req=random_number 可以防止缓存。

                【讨论】:

                  【解决方案24】:

                  我在我的 3g 路由器/调制解调器上遇到了这些方法的问题,因为如果互联网断开,路由器会将页面重定向到其响应页面,所以你仍然会得到一个蒸汽并且你的代码认为有互联网。 苹果(或其他)有一个热点检测页面,它总是返回一个特定的响应。以下示例返回“成功”响应。因此,您将完全确定您可以连接互联网并获得真正的响应!

                  public static bool CheckForInternetConnection()
                  {
                      try
                      {       
                          using (var webClient = new WebClient())
                          using (var stream = webClient.OpenRead("http://captive.apple.com/hotspot-detect.html"))
                          {
                              if (stream != null)
                              {
                                  //return true;
                                  stream.ReadTimeout = 1000;
                                  using (var reader = new StreamReader(stream, Encoding.UTF8, false))
                                  {
                                      string line;
                                      while ((line = reader.ReadLine()) != null)
                                      {
                                          if (line == "<HTML><HEAD><TITLE>Success</TITLE></HEAD><BODY>Success</BODY></HTML>")
                                          {
                                              return true;
                                          }
                                          Console.WriteLine(line);
                                      }
                                  }
                  
                              }
                              return false;
                          }
                      }
                      catch
                      {
                  
                      }
                      return false;
                  }
                  

                  【讨论】:

                    【解决方案25】:

                    我对 Internet 连接进行了三个测试。

                    • 参考System.NetSystem.Net.Sockets
                    • 添加以下测试函数:

                    测试 1

                    public bool IsOnlineTest1()
                    {
                        try
                        {
                            IPHostEntry dummy = Dns.GetHostEntry("https://www.google.com");
                            return true;
                        }
                        catch (SocketException ex)
                        {
                            return false;
                        }
                    }
                    

                    测试 2

                    public bool IsOnlineTest2()
                    {
                        try
                        {
                            IPHostEntry dummy = Dns.GetHostEntry("https://www.google.com");
                            return true;
                        }
                        catch (SocketException ex)
                        {
                            return false;
                        }
                    }
                    

                    测试 3

                    public bool IsOnlineTest3()
                    {
                        System.Net.WebRequest req = System.Net.WebRequest.Create("https://www.google.com");
                        System.Net.WebResponse resp = default(System.Net.WebResponse);
                        try
                        {
                            resp = req.GetResponse();
                            resp.Close();
                            req = null;
                            return true;
                        }
                        catch (Exception ex)
                        {
                            req = null;
                            return false;
                        }
                    }
                    

                    执行测试

                    如果您将StringBoolean 中的Dictionary 称为CheckList,则可以将每个测试的结果添加到CheckList

                    现在,使用 for...each 循环遍历每个 KeyValuePair

                    如果CheckList 包含Valuetrue,那么您就知道有互联网连接。

                    【讨论】:

                      【解决方案26】:
                      public static bool HasConnection()
                      {
                          try
                          {
                              System.Net.IPHostEntry i = System.Net.Dns.GetHostEntry("www.google.com");
                              return true;
                          }
                          catch
                          {
                              return false;
                          }
                      }
                      

                      有效

                      【讨论】:

                      • 如果你的 DNS 缓存中有 google 的 IP,它不会发送 DNS 请求,所以即使你没有连接它也会返回 true
                      猜你喜欢
                      • 2023-03-17
                      • 1970-01-01
                      • 1970-01-01
                      • 2014-03-29
                      • 1970-01-01
                      相关资源
                      最近更新 更多