.NETでインターネット接続を確認する最も速くて効率的な方法は何ですか?
Windows NLM API
これに最適なはずです。stackoverflow.com/questions/5405895/...
.NETでインターネット接続を確認する最も速くて効率的な方法は何ですか?
Windows NLM API
これに最適なはずです。stackoverflow.com/questions/5405895/...
回答:
このようなものが動作するはずです。
public static bool CheckForInternetConnection()
{
try
{
using (var client = new WebClient())
using (client.OpenRead("http://google.com/generate_204"))
return true;
}
catch
{
return false;
}
}
I cannot image a world where www.google.com does not return some HTML
例えば中国では...
インターネット接続の有無を確実に確認する方法はまったくありません(インターネットへのアクセスを意味していると思います)。
ただし、google.comへのpingなど、実質的にオフラインになることのないリソースをリクエストすることはできます。これは効率的だと思います。
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);
return (reply.Status == IPStatus.Success);
}
catch (Exception) {
return false;
}
8.8.8.8
または8.8.4.4
)へのpingは、私にとってはうまく機能します。
Beware - many schools and offices block the ping protocol.
クライアントが使用するアプリケーションにこの方法を使用している場合は、このインターネットチェック方法に反対することをお勧めします
チェックする代わりに、アクション(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
NetworkInterface.GetIsNetworkAvailable
非常に信頼できません。VMwareまたは他のLAN接続があると、間違った結果が返されます。またについてDns.GetHostEntry
方法については、アプリケーションがデプロイされる環境でテスト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);
}
Googleにpingすることによるインターネット接続のテスト:
new Ping().Send("www.google.com.mx").Status == IPStatus.Success
「タスクの実行前に接続を確認すると、接続が失われる可能性があるので、確認するポイントは何ですか」という意見には同意しません。私たち開発者が行う多くのプログラミングタスクには確かにある程度の不確実性がありますが、不確実性を許容レベルまで低減することは、課題の一部です。
最近、オンラインタイルサーバーにリンクされたマッピング機能を含むアプリケーションを作成するこの問題に遭遇しました。この機能は、インターネット接続の不足が指摘された場合は無効にされていました。
このページの応答の一部は非常に良好でしたが、主に接続がない場合に、ハングなどの多くのパフォーマンスの問題を引き起こしました。
これらの回答のいくつかと私の同僚の助けを借りて、私が最終的に使用したソリューションは次のとおりです。
// Insert this where check is required, in my case program start
ThreadPool.QueueUserWorkItem(CheckInternetConnectivity);
}
void CheckInternetConnectivity(object state)
{
if (System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable())
{
using (WebClient webClient = new WebClient())
{
webClient.CachePolicy = new System.Net.Cache.RequestCachePolicy(System.Net.Cache.RequestCacheLevel.BypassCache);
webClient.Proxy = null;
webClient.OpenReadCompleted += webClient_OpenReadCompleted;
webClient.OpenReadAsync(new Uri("<url of choice here>"));
}
}
}
volatile bool internetAvailable = false; // boolean used elsewhere in code
void webClient_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
if (e.Error == null)
{
internetAvailable = true;
Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
{
// UI changes made here
}));
}
}
私は上記のすべてのオプションを見てきましたが、インターネットが利用可能かどうかを確認する唯一の実行可能なオプションは、「Ping」オプションです。 クラスのインポート [DllImport("Wininet.dll")]
や System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces()
その他のバリエーションは NetworkInterface
、ネットワークの可用性の検出にうまく機能しません。これらのメソッドは、ネットワークケーブルが接続されているかどうかのみをチェックします。
「Pingオプション」
if
(接続が可能です)リターン true
if
(接続が利用できず、ネットワークケーブルが接続されている)リターン false
if
(ネットワークケーブルが接続されていません) Throws an exception
NetworkInterface
if
(インターネット利用可能) True
if
(インターネットは利用できず、ネットワークケーブルは接続されています) True
if
(ネットワークケーブルが接続されていません) false
[DllImport( "Wininet.dll")]
if
(インターネット利用可能) True
if
(インターネットは利用できず、ネットワークケーブルは接続されています) True
if
(ネットワークケーブルが接続されていません) false
以下の場合はそう[DllImport("Wininet.dll")]
と NetworkInterface
インターネット接続が利用可能であるかどうかを知る方法はありません。
コードのチェックと実行の間にネットワークがダウンする問題は解決しませんが、かなり信頼できます
public static bool IsAvailableNetworkActive()
{
// only recognizes changes related to Internet adapters
if (System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable())
{
// however, this will include all adapters -- filter by opstatus and activity
NetworkInterface[] interfaces = System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces();
return (from face in interfaces
where face.OperationalStatus == OperationalStatus.Up
where (face.NetworkInterfaceType != NetworkInterfaceType.Tunnel) && (face.NetworkInterfaceType != NetworkInterfaceType.Loopback)
select face.GetIPv4Statistics()).Any(statistics => (statistics.BytesReceived > 0) && (statistics.BytesSent > 0));
}
return false;
}
google.comにpingを実行すると、DNS解決の依存関係が導入されます。8.8.8.8へのpingは問題ありませんが、Googleは私から数ホップ離れています。私がしなければならないのは、インターネット上で最も近いものにpingを送信することだけです。
PingのTTL機能を使用して、ホップ#1、次にホップ#2などにpingを送信し、ルーティング可能なアドレスにあるものから応答が得られるまで続けます。そのノードがルーティング可能なアドレス上にある場合、それはインターネット上にあります。ほとんどの人にとって、ホップ#1はローカルゲートウェイ/ルーターであり、ホップ#2はファイバー接続の反対側の最初のポイントなどです。
このコードは私にとっては機能し、このスレッドの他の提案よりも速く応答します。これは、インターネット上で私に最も近いものにpingを送信するためです。
using System.Net;
using System.Net.Sockets;
using System.Net.NetworkInformation;
using System.Diagnostics;
internal static bool ConnectedToInternet()
{
const int maxHops = 30;
const string someFarAwayIpAddress = "8.8.8.8";
// Keep pinging further along the line from here to google
// until we find a response that is from a routable address
for (int ttl = 1; ttl <= maxHops; ttl++)
{
Ping pinger = new Ping();
PingOptions options = new PingOptions(ttl, true);
byte[] buffer = new byte[32];
PingReply reply = null;
try
{
reply = pinger.Send(someFarAwayIpAddress, 10000, buffer, options);
}
catch (System.Net.NetworkInformation.PingException pingex)
{
Debug.Print("Ping exception (probably due to no network connection or recent change in network conditions), hence not connected to internet. Message: " + pingex.Message);
return false;
}
System.Diagnostics.Debug.Print("Hop #" + ttl.ToString() + " is " + (reply.Address == null ? "null" : reply.Address.ToString()) + ", " + reply.Status.ToString());
if (reply.Status != IPStatus.TtlExpired && reply.Status != IPStatus.Success)
{
Debug.Print("Hop #" + ttl.ToString() + " is " + reply.Status.ToString() + ", hence we are not connected.");
return false;
}
if (IsRoutableAddress(reply.Address))
{
System.Diagnostics.Debug.Print("That's routable so you must be connected to the internet.");
return true;
}
}
return false;
}
private static bool IsRoutableAddress(IPAddress addr)
{
if (addr == null)
{
return false;
}
else if (addr.AddressFamily == AddressFamily.InterNetworkV6)
{
return !addr.IsIPv6LinkLocal && !addr.IsIPv6SiteLocal;
}
else // IPv4
{
byte[] bytes = addr.GetAddressBytes();
if (bytes[0] == 10)
{ // Class A network
return false;
}
else if (bytes[0] == 172 && bytes[1] >= 16 && bytes[1] <= 31)
{ // Class B network
return false;
}
else if (bytes[0] == 192 && bytes[1] == 168)
{ // Class C network
return false;
}
else
{ // None of the above, so must be routable
return true;
}
}
}
ここだ、それがアンドロイドに実装されていますか。
概念実証として、このコードをC#に翻訳しました。
var request = (HttpWebRequest)WebRequest.Create("http://g.cn/generate_204");
request.UserAgent = "Android";
request.KeepAlive = false;
request.Timeout = 1500;
using (var response = (HttpWebResponse)request.GetResponse())
{
if (response.ContentLength == 0 && response.StatusCode == HttpStatusCode.NoContent)
{
//Connection to internet available
}
else
{
//Connection to internet not available
}
}
private bool ping()
{
System.Net.NetworkInformation.Ping pingSender = new System.Net.NetworkInformation.Ping();
System.Net.NetworkInformation.PingReply reply = pingSender.Send(address);
if (reply.Status == System.Net.NetworkInformation.IPStatus.Success)
{
return true;
}
else
{
return false;
}
}
別のオプションは、VistaおよびWindows 7で利用可能なネットワークリストマネージャーAPI です。この記事には、これを可能にするコードサンプルをダウンロードするためのリンクがあります。
AppNetworkListUser nlmUser = new AppNetworkListUser();
Console.WriteLine("Is the machine connected to internet? " + nlmUser.NLM.IsConnectedToInternet.ToString());
[COM]タブからネットワークリスト1.0タイプライブラリへの参照を必ず追加してください。NETWORKLISTとして表示されます。
例外をキャッチして、接続のテストを回避するようにしてください。なぜなら、ネットワーク接続が失われることもあるからです。
if (NetworkInterface.GetIsNetworkAvailable() &&
new Ping().Send(new IPAddress(new byte[] { 8, 8, 8, 8 }),2000).Status == IPStatus.Success)
//is online
else
//is offline
ネットワーク/接続の変更が発生するたびにユーザーに通知/アクションを実行する場合。
NLM APIを使用します。
個人的にはAntonとmoffeltjeの答えが一番良いと思いますが、VMWareなどで設定した仮想ネットワークを除外するチェックを入れました。
public static bool IsAvailableNetworkActive()
{
// only recognizes changes related to Internet adapters
if (!System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable()) return false;
// however, this will include all adapters -- filter by opstatus and activity
NetworkInterface[] interfaces = System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces();
return (from face in interfaces
where face.OperationalStatus == OperationalStatus.Up
where (face.NetworkInterfaceType != NetworkInterfaceType.Tunnel) && (face.NetworkInterfaceType != NetworkInterfaceType.Loopback)
where (!(face.Name.ToLower().Contains("virtual") || face.Description.ToLower().Contains("virtual")))
select face.GetIPv4Statistics()).Any(statistics => (statistics.BytesReceived > 0) && (statistics.BytesSent > 0));
}
bool bb = System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable();
if (bb == true)
MessageBox.Show("Internet connections are available");
else
MessageBox.Show("Internet connections are not available");
bb
、ネットワークがインターネットに接続されていない場合でも当てはまります。
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";
}
}
}
それは不可能ではないと思います、単純ではありません。
私はこのようなものを構築しましたが、それは完璧ではありませんが、最初のステップは不可欠です。ネットワーク接続があるかどうかを確認することです。Windows APIは素晴らしい仕事をしていないので、もっと良い仕事をしてみませんか?
bool NetworkIsAvailable()
{
var all = System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces();
foreach (var item in all)
{
if (item.NetworkInterfaceType == NetworkInterfaceType.Loopback)
continue;
if (item.Name.ToLower().Contains("virtual") || item.Description.ToLower().Contains("virtual"))
continue; //Exclude virtual networks set up by VMWare and others
if (item.OperationalStatus == OperationalStatus.Up)
{
return true;
}
}
return false;
}
非常にシンプルですが、特にさまざまなプロキシ構成をチェックする場合に、チェックの品質を向上させるのに役立ちます。
そう:
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;
}
}
NetworkMonitorを使用するをネットワークの状態とインターネット接続を監視します。
サンプル:
namespace AmRoNetworkMonitor.Demo
{
using System;
internal class Program
{
private static void Main()
{
NetworkMonitor.StateChanged += NetworkMonitor_StateChanged;
NetworkMonitor.StartMonitor();
Console.WriteLine("Press any key to stop monitoring.");
Console.ReadKey();
NetworkMonitor.StopMonitor();
Console.WriteLine("Press any key to close program.");
Console.ReadKey();
}
private static void NetworkMonitor_StateChanged(object sender, StateChangeEventArgs e)
{
Console.WriteLine(e.IsAvailable ? "Is Available" : "Is Not Available");
}
}
}
前書き
一部のシナリオでは、WindowsアプリケーションでC#コードを使用してインターネットが利用可能かどうかを確認する必要があります。Windowsフォームでインターネットを使用してファイルをダウンロードまたはアップロードしたり、遠隔地にあるデータベースからデータを取得したりする場合があります。これらの状況では、インターネットチェックが必須です。
コードビハインドからC#を使用してインターネットの可用性を確認する方法はいくつかあります。このような方法はすべて、制限を含めてここで説明されています。
'wininet' APIを使用して、ローカルシステムがアクティブなインターネット接続を持っているかどうかを確認できます。これに使用される名前空間は「System.Runtime.InteropServices」であり、DllImportを使用してDLL「wininet.dll」をインポートします。この後、例に示すように、extern staticのブール変数を作成し、関数名InternetGetConnectedStateに2つのパラメーターdescriptionとreservedValueを設定します。
注:外部修飾子は、外部で実装されるメソッドを宣言するために使用されます。extern修飾子の一般的な用途は、Interopサービスを使用してアンマネージコードを呼び出すときにDllImport属性を使用することです。この場合、メソッドも静的として宣言する必要があります。
次に、ブール値として「IsInternetAvailable」という名前のメソッドを作成します。上記の関数は、ローカルシステムのインターネットステータスを返すこのメソッドで使用されます
[DllImport("wininet.dll")]
private extern static bool InternetGetConnectedState(out int description, int reservedValue);
public static bool IsInternetAvailable()
{
try
{
int description;
return InternetGetConnectedState(out description, 0);
}
catch (Exception ex)
{
return false;
}
}
次の例では、GetIsNetworkAvailableメソッドを使用して、ネットワーク接続が利用可能かどうかを判断します。
if (System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable())
{
System.Windows.MessageBox.Show("This computer is connected to the internet");
}
else
{
System.Windows.MessageBox.Show("This computer is not connected to the internet");
}
備考(MSDNによる):ネットワーク接続は、「アップ」とマークされており、ループバックまたはトンネルインターフェースではない場合、利用可能と見なされます。
デバイスまたはコンピューターが有用なネットワークに接続されていないが、まだ利用可能であると見なされ、GetIsNetworkAvailableがtrueを返す場合が多くあります。たとえば、アプリケーションを実行しているデバイスがプロキシを必要とするワイヤレスネットワークに接続されているが、プロキシが設定されていない場合、GetIsNetworkAvailableはtrueを返します。GetIsNetworkAvailableがtrueを返すもう1つの例は、ハブまたはルーターがアップストリーム接続を失ったハブまたはルーターに接続されているコンピューターでアプリケーションが実行されている場合です。
PingおよびPingReplyクラスを使用すると、アプリケーションは、ホストから応答を取得することにより、ネットワーク経由でリモートコンピューターにアクセスできるかどうかを判断できます。これらのクラスは、System.Net.NetworkInformation名前空間で使用できます。次の例は、ホストにpingする方法を示しています。
protected bool CheckConnectivity(string ipAddress)
{
bool connectionExists = false;
try
{
System.Net.NetworkInformation.Ping pingSender = new System.Net.NetworkInformation.Ping();
System.Net.NetworkInformation.PingOptions options = new System.Net.NetworkInformation.PingOptions();
options.DontFragment = true;
if (!string.IsNullOrEmpty(ipAddress))
{
System.Net.NetworkInformation.PingReply reply = pingSender.Send(ipAddress);
connectionExists = reply.Status ==
System.Net.NetworkInformation.IPStatus.Success ? true : false;
}
}
catch (PingException ex)
{
Logger.LogException(ex.Message, ex);
}
return connectionExists;
}
備考(MSDNによる):アプリケーションはPingクラスを使用して、リモートコンピューターが到達可能かどうかを検出します。ネットワークトポロジは、Pingがリモートホストに正常に接続できるかどうかを判断できます。プロキシ、ネットワークアドレス変換(NAT)機器、またはファイアウォールの存在と構成が原因で、Pingが成功しない場合があります。pingが成功するのは、リモートホストにネットワーク上で到達できることだけです。リモートホスト上の上位レベルのサービス(Webサーバーなど)の存在は保証されません。
コメント/提案が招待されています。幸せなコーディング......!
私のアプリケーションでは、小さなファイルをダウンロードしてテストします。
string remoteUri = "https://www.microsoft.com/favicon.ico"
WebClient myWebClient = new WebClient();
try
{
byte[] myDataBuffer = myWebClient.DownloadData (remoteUri);
if(myDataBuffer.length > 0) // Or add more validate. eg. checksum
{
return true;
}
}
catch
{
return false;
}
また。一部のISPは、ミドルサーバーを使用してファイルをキャッシュします。ランダムな未使用のパラメータを追加します。https://www.microsoft.com/favicon.ico?req=random_number キャッシュを防止できます。
私の3gルーター/モデムでこれらの方法に問題があります。インターネットが切断されている場合、ルーターがページをその応答ページにリダイレクトするため、まだ蒸気が発生し、コードはインターネットがあると考えています。アップル(またはその他)には、常に特定の応答を返すホットスポット専用ページがあります。次のサンプルは、「成功」応答を返します。したがって、インターネットに接続して実際の応答を得ることができると確信できます。
public static bool CheckForInternetConnection()
{
try
{
using (var webClient = new WebClient())
using (var stream = webClient.OpenRead("http://captive.apple.com/hotspot-detect.html"))
{
if (stream != null)
{
//return true;
stream.ReadTimeout = 1000;
using (var reader = new StreamReader(stream, Encoding.UTF8, false))
{
string line;
while ((line = reader.ReadLine()) != null)
{
if (line == "<HTML><HEAD><TITLE>Success</TITLE></HEAD><BODY>Success</BODY></HTML>")
{
return true;
}
Console.WriteLine(line);
}
}
}
return false;
}
}
catch
{
}
return false;
}
インターネット接続のテストは3つあります。
System.Net
とSystem.Net.Sockets
テスト1
public bool IsOnlineTest1()
{
try
{
IPHostEntry dummy = Dns.GetHostEntry("https://www.google.com");
return true;
}
catch (SocketException ex)
{
return false;
}
}
テスト2
public bool IsOnlineTest2()
{
try
{
IPHostEntry dummy = Dns.GetHostEntry("https://www.google.com");
return true;
}
catch (SocketException ex)
{
return false;
}
}
テスト3
public bool IsOnlineTest3()
{
System.Net.WebRequest req = System.Net.WebRequest.Create("https://www.google.com");
System.Net.WebResponse resp = default(System.Net.WebResponse);
try
{
resp = req.GetResponse();
resp.Close();
req = null;
return true;
}
catch (Exception ex)
{
req = null;
return false;
}
}
テストの実行
あなたが作る場合Dictionary
のString
とBoolean
呼ばれるCheckList
、あなたは、各テストの結果を追加することができますCheckList
。
次に、ループKeyValuePair
を使用してそれぞれを再帰しfor...each
ます。
もしがCheckList
含まれているValue
のをtrue
、あなたは、インターネット接続がある知っています。
public static bool HasConnection()
{
try
{
System.Net.IPHostEntry i = System.Net.Dns.GetHostEntry("www.google.com");
return true;
}
catch
{
return false;
}
}
うまくいく