C# 测试互联网连接的最快方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/843810/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 03:50:50  来源:igfitidea点击:

Fastest way to test internet connection

c#networking

提问by ant2009

C# 2008 SP1

C# 2008 SP1

I am using this code to connect to our client website. This is for a softphone application. Before the user makes a call, the softphone has to test if there is an active Internet connection.

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

So, want I have done is used the httpWebRequest class to connect to our clients website. If the response is ok, then the Internet connection can proceed.

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

However, I have noticed that the response is taking too long to respond. I am not sure if this is not a very efficient way to test.

但是,我注意到响应需要很长时间才能响应。我不确定这是否不是一种非常有效的测试方式。

However, when I browse to their website, it takes less than a second to load the page. But takes too long when I use the HttpWebRequest class

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

So requirements for this are:

所以对此的要求是:

Sometime a proxy will be used at the client's office. To I can't use the TCPClient class (doesn't have a proxy property).

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

The proxy doesn't support SOCKS so cannot use the Sockets class.

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

I need to use a timeout property. So cannot use the WebClient class. This is because the softphone would freeze until a response is returned. So timeout after a few seconds.

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

So the only one I can think of is the HttpWebRequest class.

所以我唯一能想到的就是 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;
            }

======== Edit using p\Invoke ====

======== 使用 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);

回答by Reed Copsey

Try using P/Invoke to call InternetGetConnectedState. That should tell you whether or not you have a connection configured. You can then try checking the specific connection to your service using InternetCheckConnection. This is (sometimes) quicker than hooking up the connection directly, but I'd test it to see if it's any better than just doing a full connection up front.

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

回答by Jon Skeet

What is the softphone going to use for its real communication? Is that going over HTTP/HTTPS to the same web site? If so, that's absolutely the right way to go - the next step is to work out why it's taking so long.

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

Is the network connection definitely up before you may the request? Are you definitely notmaking any requests beforehand? I ask because I notice you're not disposing of the response - if that happens elsewhere as well, you may find that you're running up against the connection pool only giving you a couple of connections to a particular server. The moral is to alwaysput HttpWebResponses in a usingstatement. Of course, that may well notbe the problem in your case, but it's worth a try.

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

If your actual application is going to connect elsewhere, then that's where your test should check as well. Basically, make it as close to the real thing as possible.

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

Out of interest, you say it's a "softphone" application - is this actually running ona phone of some description, using the compact framework, or is it a desktop app?

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

回答by Richard Watson

You can reference the Microsoft.VisualBasic.Devices namespace to use the NetworkAvailableEventHandler delegate and Network class. I use Network.IsAvailable property and Network.NetworkAvailabilityChanged event to check that the network is there (or is affected later), and then do an HTTP GET to my server to see if the server is there.

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

This helps with reporting the issue a bit more specifically, instead of "can't see network".

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

回答by Brian ONeil

I had a similar situation where we were going to make a WCF call to a client and it would take too long if the client wasn't reachable (for whatever reason). What I did was open a raw TCP socket to the client address... This fails quickly if the client is not listening at the port (in your case port 80) and succeeds quickly if they are there.

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

This gave me the fastest and most accurate answer to determine if I would be able to communicate with the endpoint that I was trying to reach. The only down side of this is that you have to manage the timeout yourself on the socket because there are only options for Send and Receive timeouts not connect.

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

It goes something like this...

它是这样的......

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

I don't have the actual code that I used in front of me, but this should put you on the general path.

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

回答by Enyo Ginger

A better option is to add reference to the Microsoft.VisualBasic and add a using statement Microsoft.VisualBasic.Device then you can use the following line of code to check for connection to any network at all.

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

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

回答by Nyerguds

request.GetResponse()itselfwill give you an exception if the host name can't be resolved, though, so you might want to put a try-catch around that, catch System.Net.WebException, and check its error status in the Statusproperty. I'm not sure which statuses exactly would indicate no internet, though; most responses could just as well be due to dns or other connection problems.

request.GetResponse()但是,如果主机名无法解析,它本身会给你一个异常,所以你可能想要在它周围放置一个 try-catch , catch System.Net.WebException,并在Status属性中检查它的错误状态。不过,我不确定哪些状态会表明没有互联网;大多数响应也可能是由于 dns 或其他连接问题。