使用 .NET 检查 Internet 连接的最佳方法是什么?
在 .NET 中检查 Internet 连接的最快、最有效的方法是什么?
What is the fastest and most efficient way to check for Internet connectivity in .NET?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(28)
您可以使用此代码,它也应该适用于伊朗和中国 -
You could use this code, which should also work in Iran and China-
您绝对无法可靠检查是否有互联网连接(我假设您的意思是访问互联网)。
但是,您可以请求几乎从不离线的资源,例如 ping google.com 或类似的东西。我认为这会很有效率。
There is absolutely no way you can reliably check if there is an internet connection or not (I assume you mean access to the internet).
You can, however, request resources that are virtually never offline, like pinging google.com or something similar. I think this would be efficient.
无需进行检查,只需执行操作(Web 请求、邮件、FTP 等),并为请求失败做好准备,即使检查成功,您也必须这样做。
请考虑以下事项:
如果网络出现故障,您的操作将像 ping 等操作一样快速失败。
Instead of checking, just perform the action (web request, mail, ftp, etc.) and be prepared for the request to fail, which you have to do anyway, even if your check was successful.
Consider the following:
If the network is down your action will fail just as rapidly as a ping, etc.
NetworkInterface.GetIsNetworkAvailable
非常不可靠。只要有一些 VMware 或其他 LAN 连接,它就会返回错误的结果。另外,关于
Dns.GetHostEntry
方法,我只是担心测试 URL 是否可能在我的应用程序要部署的环境中被阻止。所以我发现的另一种方法是使用 InternetGetConnectedState 方法。
我的代码是
NetworkInterface.GetIsNetworkAvailable
is very unreliable. Just have some VMware or other LAN connection and it will return wrong result.Also about
Dns.GetHostEntry
method I were just concerned about whether test URL might be blocked in the environment where my application going to deploy.So another way I found out is using
InternetGetConnectedState
method.My code is
Ping google.com 引入了 DNS 解析依赖性。 Ping
8.8.8.8
没问题,但 Google 离我还差好几跳。我需要做的就是 ping 互联网上离我最近的东西。我可以使用 Ping 的 TTL 功能来 ping 跳#1,然后跳#2,依此类推,直到我从可路由地址上的某个地址获得回复;如果该节点位于可路由地址上,则它位于互联网上。对于我们大多数人来说,跳#1 将是我们的本地网关/路由器,跳#2 将是光纤连接另一侧的第一个点或其他点。
这段代码对我有用,并且比该线程中的其他一些建议响应得更快,因为它正在 ping 互联网上离我最近的任何地方。
Pinging google.com introduces a DNS resolution dependency. Pinging
8.8.8.8
is fine but Google is several hops away from me. All I need to do is to ping the nearest thing to me that is on the internet.I can use
Ping
's TTL feature to ping hop #1, then hop #2, etc, until I get a reply from something that is on a routable address; if that node is on a routable address then it is on the internet. For most of us, hop #1 will be our local gateway/router, and hop #2 will be the first point on the other side of our fibre connection or whatever.This code works for me, and responds quicker than some of the other suggestions in this thread because it is pinging whatever is nearest to me on the internet.
通过 ping Google 测试互联网连接:
A test for internet connection by pinging Google:
我不同意有人说:“在执行任务之前检查连接有什么意义,因为检查后连接可能会立即丢失”。
当然,作为开发人员,我们承担的许多编程任务都存在一定程度的不确定性,但将不确定性降低到可接受的水平是挑战的一部分。
我最近在制作一个应用程序时遇到了这个问题,该应用程序包含链接到在线图块服务器的映射功能。如果发现缺乏互联网连接,则将禁用此功能。
此页面上的一些响应非常好,但确实导致了很多性能问题,例如挂起,主要是在没有连接的情况下。
在其中一些答案和我的同事的帮助下,这是我最终使用的解决方案:
I disagree with people who are stating: "What's the point in checking for connectivity before performing a task, as immediately after the check the connection may be lost".
Surely there is a degree of uncertainty in many programming tasks we as developers undertake, but reducing the uncertainty to a level of acceptance is part of the challenge.
I recently ran into this problem making an application which including a mapping feature which linked to an on-line tile server. This functionality was to be disabled where a lack of internet connectivity was noted.
Some of the responses on this page were very good, but did however cause a lot of performance issues such as hanging, mainly in the case of the absence of connectivity.
Here is the solution that I ended up using, with the help of some of these answers and my colleagues:
我已经看到了上面列出的所有选项,检查互联网是否可用的唯一可行选项是“Ping”选项。
导入
[DllImport("Wininet.dll")]
和System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces()
或NetworkInterface
的任何其他变体> 类在检测网络可用性方面效果不佳。这些方法仅检查网络电缆是否已插入。“Ping 选项”
if
(连接可用)返回true
if
(连接不可用并且网络电缆已插入)返回false
if
(网络电缆未插入)抛出异常
网络接口
< code>if(互联网可用)返回
True
if
(互联网不可用且网线已插入)返回True
if
(网络电缆未插入)返回false
[DllImport("Wininet.dll")]
if
(互联网可用)返回True
if
(互联网不可用且网线已插入)返回True
if(网络电缆未插入)返回
false
因此,在
[DllImport("Wininet.dll")]
和NetworkInterface
的情况下无法知道互联网连接是否可用。I have seen all the options listed above and the only viable option to check wither the internet is available or not is the "Ping" option.
Importing
[DllImport("Wininet.dll")]
andSystem.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces()
Or any other variation of theNetworkInterface
class does not work well in detecting the availability of the network.These Methods only check if the network cable is plugged in or not.The "Ping option"
if
(Connection is available) returnstrue
if
(Connection is not available and the network cable is plugged in) returnsfalse
if
(Network cable is not plugged in)Throws an exception
The NetworkInterface
if
(Internet Is available)ReturnsTrue
if
(Internet is not Available and Network Cable is Plugged in ) ReturnsTrue
if
(Network Cable is Not Plugged in )returnsfalse
The [DllImport("Wininet.dll")]
if
(Internet Is available)ReturnsTrue
if
(Internet is not Available and Network Cable is Plugged in ) ReturnsTrue
if
(Network Cable is Not Plugged in )returnsfalse
So in case of
[DllImport("Wininet.dll")]
andNetworkInterface
There is no way of knowing if internet connection is available.不能解决检查和运行代码之间网络中断的问题
但相当可靠
Does not solve the problem of network going down between checking and running your code
but is fairly reliable
以下是它在 Android 中的实现方式。
作为概念证明,我将此代码翻译为 C#:
Here's how it is implemented in Android.
As a proof of concept, I translated this code to C#:
简介
在某些情况下,您需要在 Windows 应用程序中使用 C# 代码检查互联网是否可用。可能是在 Windows 窗体中使用互联网下载或上传文件,或者从远程位置的数据库获取一些数据,在这些情况下,必须进行互联网检查。
有一些方法可以使用 C# 从代码隐藏中检查互联网可用性。这里解释了所有这些方法,包括它们的局限性。
'wininet' API 可用于检查本地系统是否具有活动的互联网连接。用于此目的的命名空间是“System.Runtime.InteropServices”,并使用 DllImport 导入 dll“wininet.dll”。之后,创建一个带有 extern static 的布尔变量,其函数名称为 InternetGetConnectedState,并带有两个参数 description 和 returnedValue,如示例中所示。
注意:extern 修饰符用于声明外部实现的方法。当您使用 Interop 服务调用非托管代码时,extern 修饰符的常见用途是与 DllImport 属性一起使用。在这种情况下,该方法也必须声明为静态的。
以下示例使用 GetIsNetworkAvailable 方法来确定网络连接是否可用。
备注(根据 MSDN):如果任何网络接口标记为“启动”并且不是环回或隧道接口,则认为网络连接可用。
在许多情况下,设备或计算机未连接到有用的网络,但仍被视为可用,并且 GetIsNetworkAvailable 将返回 true。例如,如果运行应用程序的设备连接到需要代理的无线网络,但未设置代理,则 GetIsNetworkAvailable 将返回 true。 GetIsNetworkAvailable 返回 true 的另一个示例是,如果应用程序正在连接到集线器或路由器的计算机上运行,而集线器或路由器已丢失上游连接。
Ping 和 PingReply 类允许应用程序通过获取主机的回复来确定是否可以通过网络访问远程计算机。这些类在 System.Net.NetworkInformation 命名空间中可用。以下示例显示如何 ping 主机。
备注(根据 MSDN):应用程序使用 Ping 类来检测远程计算机是否可访问。网络拓扑可以决定 Ping 是否可以成功联系远程主机。代理、网络地址转换 (NAT) 设备或防火墙的存在和配置可能会阻止 Ping 成功。 Ping 成功仅表明网络上可以到达远程主机;不保证远程主机上存在更高级别的服务(例如 Web 服务器)。
欢迎提出意见/建议。快乐编码......!
Introduction
In some scenarios you need to check whether internet is available or not using C# code in windows applications. May be to download or upload a file using internet in windows forms or to get some data from database which is at remote location, in these situations internet check is compulsory.
There are some ways to check internet availability using C# from code behind. All such ways are explained here including their limitations.
The 'wininet' API can be used to check the local system has active internet connection or not. The namespace used for this is 'System.Runtime.InteropServices' and import the dll 'wininet.dll' using DllImport. After this create a boolean variable with extern static with a function name InternetGetConnectedState with two parameters description and reservedValue as shown in example.
Note: The extern modifier is used to declare a method that is implemented externally. A common use of the extern modifier is with the DllImport attribute when you are using Interop services to call into unmanaged code. In this case, the method must also be declared as static.
The following example uses the GetIsNetworkAvailable method to determine if a network connection is available.
Remarks (As per MSDN): A network connection is considered to be available if any network interface is marked "up" and is not a loopback or tunnel interface.
There are many cases in which a device or computer is not connected to a useful network but is still considered available and GetIsNetworkAvailable will return true. For example, if the device running the application is connected to a wireless network that requires a proxy, but the proxy is not set, GetIsNetworkAvailable will return true. Another example of when GetIsNetworkAvailable will return true is if the application is running on a computer that is connected to a hub or router where the hub or router has lost the upstream connection.
Ping and PingReply classes allows an application to determine whether a remote computer is accessible over the network by getting reply from the host. These classes are available in System.Net.NetworkInformation namespace. The following example shows how to ping a host.
Remarks (As per MSDN): Applications use the Ping class to detect whether a remote computer is reachable. Network topology can determine whether Ping can successfully contact a remote host. The presence and configuration of proxies, network address translation (NAT) equipment, or firewalls can prevent Ping from succeeding. A successful Ping indicates only that the remote host can be reached on the network; the presence of higher level services (such as a Web server) on the remote host is not guaranteed.
Comments/Suggestions are invited. Happy coding......!
尝试通过捕获异常来避免测试连接。因为我们确实期望有时我们可能会失去网络连接。
Try to avoid testing connections by catching the exception. because we really Expect that sometimes we may lose network connection.
我不认为这是不可能的,只是不简单。
我已经构建了类似的东西,是的,它并不完美,但第一步至关重要:检查是否有任何网络连接。 Windows Api 做得并不好,那么为什么不做得更好呢?
它非常简单,但确实有助于提高检查质量,特别是当您想要检查各种代理配置时。
因此:
I wouldn't think it's impossible, just not straightforward.
I've built something like this, and yes it's not perfect, but the first step is essential: to check if there's any network connectivity. The Windows Api doesn't do a great job, so why not do a better job?
It's pretty simple, but it really helps improve the quality of the check, especially when you want to check various proxy configurations.
So:
另一种选择是网络列表管理器 API,可用于 Vista 和 Windows 7。MSDN 文章 此处。文章中提供了下载代码示例的链接,您可以通过该链接执行此操作:
请务必从 COM 选项卡添加对 Network List 1.0 类型库的引用...,它将显示为 NETWORKLIST。
Another option is the Network List Manager API which is available for Vista and Windows 7. MSDN article here. In the article is a link to download code samples which allow you to do this:
Be sure to add a reference to Network List 1.0 Type Library from the COM tab... which will show up as NETWORKLIST.
我个人认为 Anton 和 moffeltje 的答案最好,但我添加了一项检查以排除 VMWare 和其他人设置的虚拟网络。
I personally find the answer of Anton and moffeltje best, but I added a check to exclude virtual networks set up by VMWare and others.
接受的答案很快就会成功,但在没有连接时失败的速度非常慢。所以我想建立一个强大的连接检查,可以更快地失败。
据说并非所有环境都支持 Pinging,因此我从接受的答案开始,并从 此处 添加了一个 WebClient,其中包含自定义超时。你可以选择任何超时,但通过 wifi 连接时,3 秒对我来说有效。我尝试添加快速迭代(1 秒),如果第一个迭代失败,则添加慢速迭代(3 秒)。但这没有意义,因为两次迭代总是失败(未连接时)或总是成功(连接时)。
我正在连接到 AWS,因为我想在连接测试通过时上传文件。
The accepted answer succeeds quickly but is very slow to fail when there is no connection. So I wanted to build a robust connection check that would fail faster.
Pinging was said to not be supported in all environments, so I started with the accepted answer and added a WebClient from here with a custom timeout. You can pick any timeout, but 3 seconds worked for me while connected via wifi. I tried adding a fast iteration (1 second), then a slow iteration (3 seconds) if the first one fails. But that made no sense since both iterations would always fail (when not connected) or always succeed (when connected).
I'm connecting to AWS since I want to upload a file when the connection test passes.
如果您想在网络/连接发生变化时通知用户/采取行动。
使用 NLM API:
https://msdn.microsoft.com/en -us/library/ee264321.aspx
http://www.codeproject.com/Articles/34650/How-to-use-the-Windows-NLM-API-获取通知
If you want to notify the user/take action whenever a network/connection change occur.
Use NLM API:
https://msdn.microsoft.com/en-us/library/ee264321.aspx
http://www.codeproject.com/Articles/34650/How-to-use-the-Windows-NLM-API-to-get-notified-of
多线程版本的 ping:
Multi threaded version of ping:
基于 @ChaosPandion 的答案,为了尽可能确保结果正确,您可以包含多个大型网站,例如其他人指出。但是,这应该异步完成,以避免等待时间过长。此外,WebRequest、HttpWebRequest 和 HttpWebResponse 类现在已过时,应由 HttpClient 替换。以下示例考虑了上述情况:
此方法检查列表中的所有 url,如果它们都无法访问,则返回 false。我添加了苹果的网址,因为在我的情况下它加载得非常快,但它可以替换为任何网址。
Building on @ChaosPandion's answer, to be as sure as possible that the result is correct you can include multiple big sites like others have pointed out. However this should be done asynchronously to avoid too long wait times. Also the WebRequest, HttpWebRequest and HttpWebResponse classes are now obsolete and should be replaced by HttpClient. The following example takes into account the above:
This method checks all the urls in the list and if they are all inaccessible then it returns false. I have added apple's url, because in my case it loads pretty fast, but it can be replaced with any url.
使用 NetworkMonitor 监控网络状态和互联网连接。
示例:
Use NetworkMonitor to monitoring network state and internet connection.
Sample:
以下代码对我来说效果很好:
The following code works fine for me:
对于我的应用程序,我们还通过下载小文件进行测试。
还。一些 ISP 可能会使用中间服务器来缓存文件。添加随机未使用的参数,例如。 https://www.microsoft.com/favicon.ico?req=random_number
可以防止缓存。
For my application we also test by download tiny file.
Also. Some ISP may use middle server to cache file. Add random unused parameter eg. https://www.microsoft.com/favicon.ico?req=random_number
Can prevent caching.
我在 3g 路由器/调制解调器上使用这些方法时遇到问题,因为如果互联网断开连接,路由器会将页面重定向到其响应页面,因此您仍然会收到蒸汽,并且您的代码认为有互联网。
苹果(或其他)有一个热点检测页面,它总是返回特定的响应。以下示例返回“成功”响应。所以您将完全确定您可以连接互联网并获得真实的响应!
I am having issue on those method on my 3g Router/modem, because if internet is disconnected the router redirects the page to its response page, so you still get a steam and your code think there is internet.
Apples (or others) have a hot-spot-dedection page which always returns a certain response. The following sample returns "Success" response. So you will be exactly sure you could connect the internet and get real response !
我对互联网连接进行了三个测试。
System.Net
和System.Net.Sockets
测试1
测试2
测试 3
执行测试
如果您创建一个名为
String
和Boolean
的字典
>CheckList,您可以将每次测试的结果添加到CheckList
中。现在,使用
for...each
循环递归每个KeyValuePair
。如果
CheckList
包含Value
为true
,则您知道存在 Internet 连接。I have three tests for an Internet connection.
System.Net
andSystem.Net.Sockets
Test 1
Test 2
Test 3
Performing the tests
If you make a
Dictionary
ofString
andBoolean
calledCheckList
, you can add the results of each test toCheckList
.Now, recurse through each
KeyValuePair
using afor...each
loop.If
CheckList
contains aValue
oftrue
, then you know there is an Internet connection.那行得通
That works