【问题标题】:Fastest way to test internet connection测试互联网连接的最快方法
【发布时间】:2010-10-25 00:50:39
【问题描述】:

C# 2008 SP1

我正在使用此代码连接到我们的客户网站。这是针对软件电话应用程序的。在用户拨打电话之前,软件电话必须测试是否有活动的 Internet 连接。

所以,我想做的是使用 httpWebRequest 类连接到我们的客户网站。如果响应正常,则可以继续进行 Internet 连接。

但是,我注意到响应时间过长。我不确定这是否不是一种非常有效的测试方法。

但是,当我浏览他们的网站时,加载页面只需不到一秒钟的时间。但是当我使用 HttpWebRequest 类时需要太长时间

所以对此的要求是:

有时会在客户办公室使用代理。我不能使用 TCPClient 类(没有代理属性)。

代理不支持 SOCKS,因此无法使用 Sockets 类。

我需要使用超时属性。所以不能使用 WebClient 类。这是因为软件电话会冻结,直到返回响应。所以几秒钟后超时。

所以我唯一能想到的就是 HttpWebRequest 类。

  HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://www.xxxxxxxxx.com");
            request.Timeout = 5000;
            request.Credentials = CredentialCache.DefaultNetworkCredentials;
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();

            if (response.StatusCode == HttpStatusCode.OK)
            {
                Console.WriteLine("IsSIPServerAvailable: " + response.StatusCode);
                isAvailable = true;
            }

======== 使用 p\Invoke 编辑 ====

 [DllImport("wininet.dll", CharSet = CharSet.Auto)]
    private extern static bool InternetGetConnectedState(ref InternetConnectionState_e lpdwFlags, int dwReserved);

 [Flags]
    enum InternetConnectionState_e : int
    {
        INTERNET_CONNECTION_MODEM = 0x1,
        INTERNET_CONNECTION_LAN = 0x2,
        INTERNET_CONNECTION_PROXY = 0x4,
        INTERNET_RAS_INSTALLED = 0x10,
        INTERNET_CONNECTION_OFFLINE = 0x20,
        INTERNET_CONNECTION_CONFIGURED = 0x40
    }

 // In function for checking internet
 InternetConnectionState_e flags = 0;          
 bool isConnected = InternetGetConnectedState(ref flags, 0);

【问题讨论】:

    标签: c# networking


    【解决方案1】:

    尝试使用 P/Invoke 调用 InternetGetConnectedState。这应该告诉您是否配置了连接。然后,您可以尝试使用InternetCheckConnection 检查与您的服务的特定连接。这(有时)比直接连接连接要快,但我会对其进行测试,看看它是否比预先进行完整连接更好。

    【讨论】:

    • 该(IMO)的缺点是它只告诉您计算机是否连接到“一般的互联网”。它只是在一定程度上表明您是否能够获得您所追求的特定服务。 IMO,最好的方法就是连接到该服务。当然,这并不能保证它在一秒钟后仍然有效,但我认为如果可能的话,它是一个更好的指标。 (在某些情况下不是这样,例如,如果只是连接会产生某种费用。)
    • 我已经为 p/Invoke 编辑了我的代码。但是,它确实告诉我 LAN 是否连接到我的计算机(插入或拔出)。但是,它无法告诉我是否有活动的 Internet 连接(浏览 Internet)。
    • @robUK:我编辑了我的答案以包括对 InternetCheckConnection 的调用。这是您可以尝试的另一个 P/Invoke - 它应该会告诉您该特定 URL 是否可用,但我相信它比尝试自己连接连接要快一些。
    【解决方案2】:

    软件电话将使用什么进行真正的通信?是通过 HTTP/HTTPS 访问同一个网站吗?如果是这样,那绝对是正确的方法 - 下一步是弄清楚为什么需要这么长时间。

    在您发出请求之前,网络连接是否已确定?您确定事先提出任何要求吗?我问是因为我注意到您没有处理响应 - 如果这也发生在其他地方,您可能会发现您正在运行连接池,只为您提供到特定服务器的几个连接。道德是始终HttpWebResponses 放入using 声明中。当然,这可能不是你的问题,但值得一试。

    如果您的实际应用程序要连接到其他地方,那么您的测试也应该检查那里。基本上,让它尽可能接近真实的东西。

    出于兴趣,您说它是一个“软电话”应用程序——它实际上是在某种描述的电话上运行,使用紧凑的框架,还是桌面应用程序?

    【讨论】:

    • 你好。它是一个桌面运行,可以在 2000、XP 和 Vista 上运行。关于 using 语句的信息。我忘记了。 SIP 服务器在同一台服务器上。但是,我可以使用 SIP 协议进行连接并使用 RTP 进行流式传输。
    • 如果你以后真的要连接SIP,为什么不连接SIP进行测试呢?您可以提出一些无操作的 SIP 请求吗?
    • 我正在调查一些 SIP 请求。我也喜欢下面的 P/invoke 选项。我想我会尝试两种选择。谢谢。
    【解决方案3】:

    我遇到过类似的情况,我们要对客户端进行 WCF 调用,如果无法访问客户端(无论出于何种原因),这将花费很长时间。我所做的是打开一个原始 TCP 套接字到客户端地址...如果客户端没有在端口(在您的情况下为端口 80)侦听,这会很快失败,如果它们在那里,则会很快成功。

    这给了我最快和最准确的答案,以确定我是否能够与我试图到达的端点进行通信。唯一的缺点是您必须自己在套接字上管理超时,因为只有发送和接收超时不连接的选项。

    事情是这样的......

    Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    
        try
        {
             IAsyncResult result = socket.BeginConnect("www.xxxxxxxxx.com", 80, null, null );
             //I set it for 3 sec timeout, but if you are on an internal LAN you can probably 
             //drop that down a little because this should be instant if it is going to work
             bool success = result.AsyncWaitHandle.WaitOne( 3000, true );
    
             if ( !success )
             {
                    throw new ApplicationException("Failed to connect server.");
             }
    
             // Success
             //... 
        }
        finally
        {
             //You should always close the socket!
             socket.Close();
        }
    

    我没有在我面前使用的实际代码,但这应该会让你走上一般道路。

    【讨论】:

    • 您好,感谢您的代码。实际上我已经尝试过套接字类。但是,我必须连接的代理服务器不支持 SOCKS 协议。如果不是代理服务器,这将是一个很好的解决方案。
    • ONiel,谢谢。我使用的是 TcpClient,它比这种方法慢得多。
    • 非常感谢这位 Google 员工!我试图找出端口 25(邮件服务器端口)是否被提供商阻止,以便我可以使用端口 2525。您的代码将该过程从 30 秒的等待时间缩短为 3 秒的等待时间。 :)
    【解决方案4】:

    您可以引用 Microsoft.VisualBasic.Devices 命名空间来使用 NetworkAvailableEventHandler 委托和 Network 类。我使用 Network.IsAvailable 属性和 Network.NetworkAvailabilityChanged 事件来检查网络是否存在(或稍后受到影响),然后对我的服务器执行 HTTP GET 以查看服务器是否存在。

    这有助于更具体地报告问题,而不是“看不到网络”。

    【讨论】:

      【解决方案5】:

      更好的选择是添加对 Microsoft.VisualBasic 的引用并添加一条 using 语句 Microsoft.VisualBasic.Device 然后您可以使用以下代码行来检查是否连接到任何网络。

      public static bool isConnectedToNetwork {
         get {
            Network network = new Network();
            return network.IsAvailable;
         }
      }
      

      【讨论】:

        【解决方案6】:

        使用异常处理。

                try
                {
                    using (WebClient client = new WebClient())
                    {
                        string htmlCode = client.DownloadString("https://www.google.com/");                    
                    }
                }
                catch
                {
                    //No Internet 
                    Console.WriteLine("No Internet")
                }
        

        【讨论】:

          【解决方案7】:
          如果无法解析主机名,

          request.GetResponse() itself 会给你一个异常,所以你可能想在它周围放置一个 try-catch,catch System.Net.WebException,然后在Status 属性中检查其错误状态。不过,我不确定哪些状态确切地表明没有互联网;大多数响应也可能是由于 dns 或其他连接问题。

          【讨论】:

            猜你喜欢
            • 2018-11-06
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-07-19
            • 1970-01-01
            • 2012-01-17
            • 2014-08-31
            • 2014-03-29
            相关资源
            最近更新 更多