使用.NET检查Internet连接的最佳方法是什么?

时间:2010-01-09 00:48:07

标签: c# .net internet-connection

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

28 个答案:

答案 0 :(得分:248)

这样的事情应该有效。

System.Net.WebClient

public static bool CheckForInternetConnection()
{
    try
    {
        using (var client = new WebClient())
        using (client.OpenRead("http://clients3.google.com/generate_204"))
        {
            return true;
        }
    }
    catch
    {
        return false;
    }
}

答案 1 :(得分:72)

绝对没有办法可靠检查是否存在互联网连接(我认为您的意思是访问互联网)。

但是,您可以请求几乎从不离线的资源,例如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;
}

答案 2 :(得分:36)

而不是检查,只需执行操作(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

答案 3 :(得分:25)

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

答案 4 :(得分:12)

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

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

答案 5 :(得分:11)

我不同意那些声明的人:"在执行任务之前检查连接的重点是什么,因为检查后连接可能会丢失"。 当然,我们作为开发人员所承担的许多编程任务存在一定程度的不确定性,但将不确定性降低到接受程度是挑战的一部分。

我最近遇到了这个问题,制作了一个包含链接到在线磁贴服务器的映射功能的应用程序。在注意到缺乏互联网连接的情况下,将禁用此功能。

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

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

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

答案 6 :(得分:8)

我已经看到了上面列出的所有选项,唯一可行的选项来检查互联网是否可用是&#34; Ping&#34;选项。 导入[DllImport("Wininet.dll")]System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces()NetworkInterface类的任何其他变体在检测网络可用性方面效果不佳。这些方法仅检查网络电缆是否已插入。

&#34; Ping选项&#34;

if(连接可用)返回true

if(连接不可用且已插入网络电缆)返回false

if(未插入网络电缆)Throws an exception

NetworkInterface

if(互联网可用)返回True

if(互联网不可用且已插入网络电缆)返回True

if(未插入网络电缆)返回false

[DllImport(&#34; Wininet.dll&#34;)]

if(互联网可用)返回True

if(互联网不可用且已插入网络电缆)返回True

if(未插入网络电缆)返回false

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

答案 7 :(得分:8)

无法解决检查和运行代码之间网络故障的问题         但相当可靠

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

答案 8 :(得分:4)

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

答案 9 :(得分:3)

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

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

答案 10 :(得分:3)

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

答案 11 :(得分:2)

另一个选项是网络列表管理器API,可用于Vista和Windows 7. MSDN文章here。在本文中有一个下载代码示例的链接,允许您执行此操作:

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

请务必在COM选项卡中添加对Network List 1.0 Type Library的引用...它将显示为NETWORKLIST。

答案 12 :(得分:2)

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

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

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

using System.Net;
using System.Net.Sockets;
using System.Net.NetworkInformation;
using System.Diagnostics;

internal static bool ConnectedToInternet()
{
    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++)
    {
        Ping pinger = new Ping();
        PingOptions options = new PingOptions(ttl, true);
        byte[] buffer = new byte[32];
        PingReply reply = null;
        try
        {
            reply = pinger.Send(someFarAwayIpAddress, 10000, buffer, options);
        }
        catch (System.Net.NetworkInformation.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;
        }

        System.Diagnostics.Debug.Print("Hop #" + ttl.ToString() + " is " + (reply.Address == null ? "null" : reply.Address.ToString()) + ", " + reply.Status.ToString());

        if (reply.Status != IPStatus.TtlExpired && reply.Status != IPStatus.Success)
        {
            Debug.Print("Hop #" + ttl.ToString() + " is " + reply.Status.ToString() + ", hence we are not connected.");
            return false;
        }

        if (IsRoutableAddress(reply.Address))
        {
            System.Diagnostics.Debug.Print("That's routable so you 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;
        }
    }
}

答案 13 :(得分:1)

我个人最好找到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));
}

答案 14 :(得分:1)

答案 15 :(得分:1)

简介

在某些情况下,您需要使用Windows应用程序中的C#代码检查Internet是否可用。可能是使用Windows窗体中的Internet下载或上传文件,或者是从位于远程位置的数据库中获取一些数据,在这种情况下,必须进行Internet检查。

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

  1. InternetGetConnectedState(wininet)

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

注意:extern修饰符用于声明在外部实现的方法。当您使用Interop服务来调用非托管代码时,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):如果任何网络接口标记为“打开”并且不是环回或隧道接口,则认为网络连接可用。

在许多情况下,设备或计算机未连接到有用的网络,但仍被认为可用,并且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 :(得分:1)

accepted answer成功快速,但是在没有连接时失败很慢。因此,我想构建一个健壮的连接检查,该检查将更快地失败。

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

我要连接到AWS,因为我想在连接测试通过后上传文件。

Alice was beginning to get very tired of sitting by her sister on the bank, 
and of having nothing to do: once or twice she had peeped into the book 
her sister was reading, but it had no pictures or conversations in it, and 
what is the use of a book, thought Alice without pictures or conversations?

答案 17 :(得分:0)

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

我已经构建了这样的东西,是的,它并不完美,但第一步是必不可少的:检查是否有任何网络连接。 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的代理配置)

答案 18 :(得分:0)

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

答案 19 :(得分:0)

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

答案 20 :(得分:0)

使用NetworkMonitor监视网络状态和Internet连接。

示例:

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

答案 21 :(得分:0)

尝试一下:

 using System.Net.NetworkInformation;
 bool isNetAvailable = NetworkInterface.GetIsNetworkAvailable();

答案 22 :(得分:0)

bool bb = System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable();

if (bb == true)
    MessageBox.Show("Internet connections are available");
else
    MessageBox.Show("Internet connections are not available");

答案 23 :(得分:0)

您可以使用NetworkInterface.GetIsNetworkAvailable方法来指示是否有任何网络连接可用。

尝试一下:

bool connection = NetworkInterface.GetIsNetworkAvailable();
if (connection == true)
 {
     MessageBox.Show("The system is online");
 }
 else {
     MessageBox.Show("The system is offline";
 }

答案 24 :(得分:-1)

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

CollapsingToolbarLayout

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

答案 25 :(得分:-1)

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

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

答案 26 :(得分:-2)

我有三个互联网连接测试。

  • 参考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;
    }
}

执行测试

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

现在,使用KeyValuePair循环递归每个for...each

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

答案 27 :(得分:-3)

public static bool HasConnection()
{
    try
    {
        System.Net.IPHostEntry i = System.Net.Dns.GetHostEntry("www.google.com");
        return true;
    }
    catch
    {
        return false;
    }
}

有效