不断检查网络连接

6

如何在我的应用程序中不断检查网络连接并在连接不可用时做出响应?

目前我正在使用以下方法:

while(true) {
 if(HasConnection()) {
     //doSomething..
  }
   //stop app by 1sec
}

但这似乎相当不优雅。

11个回答

3

在superuser上针对这个问题的被接受答案描述了Windows确定是否有网络访问的方法。你可以使用类似的方法,但我建议在应用启动时生成一个负责进行检查的独立线程。让独立线程按照你认为最好的方式执行检查,并在连接状态发生变化时引发事件。


这里是API链接:Windows Vista和Windows 7中的网络感知,这里是CodeProject文章:如何使用Windows NLM API获取新网络连接通知 - Rick Sladkey

2
请使用以下代码:
public static class LocalSystemConnection
{
    [DllImport("wininet.dll", SetLastError=true, CallingConvention = CallingConvention.ThisCall)]
    extern static bool InternetGetConnectedState(out ConnectionStates lpdwFlags, long dwReserved);

    /// <summary>
    /// Retrieves the connected state of the local system.
    /// </summary>
    /// <param name="connectionStates">A <see cref="ConnectionStates"/> value that receives the connection description.</param>
    /// <returns>
    /// A return value of true indicates that either the modem connection is active, or a LAN connection is active and a proxy is properly configured for the LAN.
    /// A return value of false indicates that neither the modem nor the LAN is connected.
    /// If false is returned, the <see cref="ConnectionStates.Configured"/> flag may be set to indicate that autodial is configured to "always dial" but is not currently active.
    /// If autodial is not configured, the function returns false.
    /// </returns>
    public static bool IsConnectedToInternet(out ConnectionStates connectionStates)
    {
        connectionStates = ConnectionStates.Unknown;
        return InternetGetConnectedState(out connectionStates, 0);
    }

    /// <summary>
    /// Retrieves the connected state of the local system.
    /// </summary>
    /// <returns>
    /// A return value of true indicates that either the modem connection is active, or a LAN connection is active and a proxy is properly configured for the LAN.
    /// A return value of false indicates that neither the modem nor the LAN is connected.
    /// If false is returned, the <see cref="ConnectionStates.Configured"/> flag may be set to indicate that autodial is configured to "always dial" but is not currently active.
    /// If autodial is not configured, the function returns false.
    /// </returns>
    public static bool IsConnectedToInternet()
    {
        ConnectionStates state = ConnectionStates.Unknown;
        return IsConnectedToInternet(out state);
    }
}

[Flags]
public enum ConnectionStates
{
    /// <summary>
    /// Unknown state.
    /// </summary>
    Unknown = 0,

    /// <summary>
    /// Local system uses a modem to connect to the Internet.
    /// </summary>
    Modem = 0x1,

    /// <summary>
    /// Local system uses a local area network to connect to the Internet.
    /// </summary>
    LAN = 0x2,

    /// <summary>
    /// Local system uses a proxy server to connect to the Internet.
    /// </summary>
    Proxy = 0x4,

    /// <summary>
    /// Local system has RAS (Remote Access Services) installed.
    /// </summary>
    RasInstalled = 0x10,

    /// <summary>
    /// Local system is in offline mode.
    /// </summary>
    Offline = 0x20,

    /// <summary>
    /// Local system has a valid connection to the Internet, but it might or might not be currently connected.
    /// </summary>
    Configured = 0x40,
}

2
你正在寻找 NetworkAvailabilityChanged 事件
要检查互联网连接,你可以 ping 一个可靠的网站,比如 Google.com。
请注意,并不可能被通知每一次互联网连接的变化(例如 ISP 停机)。

1
即使网络处于“正常”状态,也不能保证互联网可用。 - Daniel Powell
@Daniel:是的,我正要说到那个。 - SLaks

1
如果您想持续检查,则使用计时器。
    private Timer timer1;
    public void InitTimer()
    {
        timer1 = new Timer();
        timer1.Tick += new EventHandler(timerEvent);
        timer1.Interval = 2000; // in miliseconds
        timer1.Start();
    }

    private void timerEvent(object sender, EventArgs e)
    {
        DoSomeThingWithInternet();
    }

     private void DoSomeThingWithInternet()
    {
        if (isConnected())
        {
           // inform user that "you're connected to internet"
        }
        else
        {
             // inform user that "you're not connected to internet"
        }
    }

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

1

1

我知道这是一个老问题,但对我来说这非常有效。

System.Net.NetworkInformation.NetworkChange.NetworkAvailabilityChanged += NetworkChange_NetworkAvailabilityChanged;

private async void NetworkChange_NetworkAvailabilityChanged(object sender, System.Net.NetworkInformation.NetworkAvailabilityEventArgs e)
        {
            //code to execute...
        }

我会为监听器订阅事件并不断检查连接。您可以添加一个 If 语句,例如:
if (System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable())
   {
        //Send Ping...
   }
else
    {
        //other code....
    }

0

您可以通过ping一些网站来测试互联网连接,例如:

    public bool IsConnectedToInternet
    {
        try
        {
            using (System.Net.NetworkInformation.Ping ping = new System.Net.NetworkInformation.Ping())
            {
                string address = @"http://www.google.com";//                        System.Net.NetworkInformation.PingReply pingReplay = ping.Send(address);//you can specify timeout.
                if (pingReplay.Status == System.Net.NetworkInformation.IPStatus.Success)
                {
                    return true;
                }
             }
        }
        catch
        {
#if DEBUG
            System.Diagnostics.Debugger.Break();
#endif//DEBUG
        }

        return false;
    }

0

使用NetworkChange.NetworkAvailabilityChanged是最具误导性的答案。它检查的是网络可用性的变化而不是互联网连接的变化。

我们可以使用Windows NLM API来监控互联网连接。

using System;
using System.Runtime.InteropServices.ComTypes;
using NETWORKLIST;

namespace Components.Network.Helpers
{
    public class InternetConnectionChecker : INetworkListManagerEvents, IDisposable
    {
        private int _cookie;
        private IConnectionPoint _connectionPoint;
        private readonly INetworkListManager _networkListManager;

        public InternetConnectionChecker()
        {
            _networkListManager = new NetworkListManager();
        }

        public bool IsConnected()
        {
            return _networkListManager.IsConnectedToInternet;
        }

        public void StartMonitoringConnection()
        {
            try
            {
                var container = _networkListManager as IConnectionPointContainer;
                if (container == null)
                    throw new Exception("connection container is null");
                var riid = typeof(INetworkListManagerEvents).GUID;
                container.FindConnectionPoint(ref riid, out _connectionPoint);
                _connectionPoint.Advise(this, out _cookie);
            }
            catch (Exception e)
            {

            }
        }

        public void ConnectivityChanged(NLM_CONNECTIVITY newConnectivity)
        {
            if (_networkListManager.IsConnectedToInternet)
            {
                // do something based on internet connectivity
            }

        }

        public void Dispose()
        {
            _connectionPoint.Unadvise(_cookie);
        }
    }
}

0
你如何知道你是否有互联网连接?仅仅能够将数据包路由到附近的路由器就足够了吗?也许这台机器只有一个网卡、一个网关,而且可能网关的连接已经断开,但是机器仍然可以路由到网关和本地网络?
也许这台机器只有一个网卡和十几个网关;也许它们一直在变化,但其中一个始终保持在线?
如果这台机器有多个网卡,但只有一个网关呢?也许它可以路由到互联网的某些子集,但仍然与未连接到互联网的本地网络保持良好的连接?
如果这台机器有多个网卡、多个网关,但出于管理策略原因,仍然只有部分互联网是可路由的呢?
你真的只关心客户端是否连接到你的服务器吗?
什么样的数据包延迟是可以接受的?(30毫秒很好,300毫秒已经接近人类耐受极限,3000毫秒是无法忍受的长时间,960000毫秒是连接到太阳探测器所需的时间。)什么样的数据包丢失是可以接受的?
你到底想要衡量什么?

0

只是一个开始,但正如sarnold所提到的,你需要考虑很多事情。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接