在。net中检查Internet连接的最快和最有效的方法是什么?
当前回答
接受的答案很快就成功了,但当没有连接时,失败的速度非常慢。所以我想建立一个健壮的连接检查,它会更快地失败。
据说不是所有环境都支持ping,所以我从接受的答案开始,并从这里添加了一个带有自定义超时的WebClient。你可以选择任何超时,但3秒对我来说是通过wifi连接的。我尝试添加一个快速迭代(1秒),如果第一个迭代失败,则添加一个缓慢迭代(3秒)。但是这没有意义,因为这两个迭代总是失败(当没有连接时)或总是成功(当连接时)。
我正在连接AWS,因为我想在连接测试通过时上传一个文件。
public static class AwsHelpers
{
public static bool GetCanConnectToAws()
{
try
{
using (var client = new WebClientWithShortTimeout())
using (client.OpenRead("https://aws.amazon.com"))
return true;
}
catch
{
return false;
}
}
}
public class WebClientWithShortTimeout: WebClient
{
protected override WebRequest GetWebRequest(Uri uri)
{
var webRequest = base.GetWebRequest(uri);
webRequest.Timeout = 5000;
return webRequest;
}
}
其他回答
NetworkInterface。GetIsNetworkAvailable非常不可靠。只是有一些VMware或其他局域网连接,它将返回错误的结果。 还有Dns。我只是关心测试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);
}
多线程版本的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";
}
}
}
而不是检查,只需执行操作(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
根据@ChaosPandion的回答,为了尽可能确保结果是正确的,你可以像其他人指出的那样,包括多个大网站。但是,这应该异步完成,以避免太长的等待时间。此外,WebRequest、HttpWebRequest和HttpWebResponse类现在已经过时,应该被HttpClient取代。以下示例考虑了上述因素:
public static async Task<bool> CheckForInternetConnection(TimeSpan? timeoutMs = null, List<string> urls = null)
{
if (timeoutMs == null)
{
timeoutMs = TimeSpan.FromSeconds(10);
}
var culture = CultureInfo.InstalledUICulture;
if (urls == null)
{
urls = new List<string>();
if (culture.Name.StartsWith("fa")) // Iran
urls.Add("http://www.aparat.com");
else if (culture.Name.StartsWith("zh")) // China
urls.Add("http://www.baidu.com");
else
{
urls.Add("https://www.apple.com/");
urls.Add("https://www.gstatic.com/generate_204");
}
}
var client = new HttpClient();
client.Timeout = (TimeSpan)timeoutMs;
List<Task<string>> tasks = new List<Task<string>>();
int unresponsiveUrlCount = 0;
foreach (var url in urls)
{
tasks.Add(client.GetStringAsync(url));
}
Task aggregationTask = null;
try
{
aggregationTask = Task.WhenAll(tasks);
await aggregationTask;
}
catch (Exception)
{
if (aggregationTask?.Exception?.InnerExceptions != null && aggregationTask.Exception.InnerExceptions.Any())
{
foreach (var innerEx in aggregationTask.Exception.InnerExceptions)
{
unresponsiveUrlCount++;
}
}
}
return unresponsiveUrlCount < urls.Count;
}
该方法检查列表中的所有url,如果它们都不可访问,则返回false。我已经添加了苹果的url,因为在我的情况下,它加载相当快,但它可以替换为任何url。
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;
}
}
推荐文章
- 如何从枚举中选择一个随机值?
- 驻留在App_Code中的类不可访问
- 在链式LINQ扩展方法调用中等价于'let'关键字的代码
- dynamic (c# 4)和var之间的区别是什么?
- Visual Studio: ContextSwitchDeadlock
- 返回文件在ASP。Net Core Web API
- 自定义HttpClient请求头
- 如果我使用OWIN Startup.cs类并将所有配置移动到那里,我是否需要一个Global.asax.cs文件?
- VS2013外部构建错误"error MSB4019: The imported project <path> was not found"
- 从另一个列表id中排序一个列表
- 等待一个无效的异步方法
- 无法加载文件或程序集…参数不正确
- c#中枚举中的方法
- 如何从字符串中删除新的行字符?
- 如何设置一个默认值与Html.TextBoxFor?