web-dev-qa-db-ja.com

.NETを使用してインターネット接続を確認する最良の方法は何ですか?

.NETでインターネット接続を確認するための最速かつ最も効率的な方法は何ですか?

202
Mohit Deshpande

このような何かが動作するはずです。

System.Net.WebClient

public static bool CheckForInternetConnection()
{
    try
    {
        using (var client = new WebClient())
        using (client.OpenRead("http://clients3.google.com/generate_204"))
        {
            return true;
        }
    }
    catch
    {
        return false;
    }
}
250
ChaosPandion

信頼性の高いインターネット接続があるかどうかを確認する方法はまったくありません(インターネットへのアクセスを意味すると仮定します)。

ただし、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;
}
72
Leo

チェックする代わりに、アクション(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
36
dbasnett

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);         
}
25
Kamran Shahid

Googleにpingを実行してインターネット接続をテストします。

new Ping().Send("www.google.com.mx").Status == IPStatus.Success
12
Jaime Macias

「タスクの実行前に接続をチェックする意味は何ですか、チェック直後に接続が失われる可能性があります」と述べている人々には同意しません。開発者として私たちが行う多くのプログラミングタスクには確かにある程度の不確実性がありますが、不確実性を許容レベルまで減らすことは課題の一部です。

私は最近、オンラインタイルサーバーにリンクするマッピング機能を含むアプリケーションを作成する際にこの問題に遭遇しました。この機能は、インターネット接続の欠如が指摘された場合は無効にする必要がありました。

このページの応答の一部は非常に良好でしたが、主に接続性がない場合に、ハングなどのパフォーマンスの問題を引き起こしました。

これらの答えのいくつかと同僚の助けを借りて、私が最終的に使用したソリューションは次のとおりです:

         // 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
            }));
        }
    }
11
PJRobot

上記のすべてのオプションを見てきましたが、インターネットが利用可能かどうかを確認する唯一の実行可能なオプションは、「Ping」オプションです。 [DllImport("Wininet.dll")]およびSystem.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces()またはNetworkInterfaceクラスの他のバリエーションをインポートしても、ネットワークの可用性を検出するのにうまく機能しません。これらのメソッドは、ネットワークケーブルが接続されているかどうかのみをチェックします。

「Pingオプション」

if(接続が使用可能)はtrueを返します

if(接続が利用できず、ネットワークケーブルが差し込まれています)はfalseを返します

if(ネットワークケーブルが接続されていません)Throws an exception

The NetworkInterface

if(インターネットが利用可能)Trueを返します

if(インターネットが利用できず、ネットワークケーブルが差し込まれている)Trueを返します

if(ネットワークケーブルが接続されていない)が返すfalse

[DllImport( "Wininet.dll")]

if(インターネットが利用可能)Trueを返します

if(インターネットが利用できず、ネットワークケーブルが差し込まれている)Trueを返します

if(ネットワークケーブルが接続されていない)が返すfalse

したがって、[DllImport("Wininet.dll")]およびNetworkInterfaceの場合、インターネット接続が利用可能かどうかを知る方法はありません。

9
HackerMan

コードのチェックと実行の間でネットワークがダウンする問題を解決しませんが、かなり信頼できます

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;
}
8
Anton

こちら Androidでの実装方法。

概念実証として、このコードを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
    }
}
4
breez
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;
    }
}
3
Shai Segev

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;
        }
    }
}
2
Jinlye

もう1つのオプションは、VistaおよびWindows 7で使用可能なNetwork List Manager APIです。MSDNの記事 here 。記事には、これを行うことができるコードサンプルをダウンロードするためのリンクがあります。

AppNetworkListUser nlmUser = new AppNetworkListUser();
Console.WriteLine("Is the machine connected to internet? " + nlmUser.NLM.IsConnectedToInternet.ToString());

必ずCOMタブからNetwork List 1.0 Type Libraryへの参照を追加してください... NETWORKLISTとして表示されます。

2
gierow

個人的には Anton and moffeltje bestの答えを見つけましたが、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));
}
1
Spegeli

ネットワーク/接続の変更が発生するたびにユーザーに通知する/アクションを実行する場合。
NLM APIを使用:

1
Ansary Ans21

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");
        }
    }
}
0
user6695808

これを試して:

 using System.Net.NetworkInformation;
 bool isNetAvailable = NetworkInterface.GetIsNetworkAvailable();
0
Shaahin
bool bb = System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable();

if (bb == true)
    MessageBox.Show("Internet connections are available");
else
    MessageBox.Show("Internet connections are not available");
0
Hari Prasath
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;
    }
}
0
Salih Alija

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";
          }
      }
  }
0
Nime Cloud

私はそれが不可能だとは思わない、ただ単純ではない。

私はこのようなものを構築しましたが、完璧ではありませんが、最初のステップは不可欠です。ネットワーク接続があるかどうかを確認することです。 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;
}

これは非常に簡単ですが、特にさまざまなプロキシ構成を確認する場合は、チェックの品質を向上させるのに役立ちます。

そう:

  • ネットワーク接続があるかどうかを確認します(これを本当に良くします。NetworkIsAvailable関数を改善するための誤検知がある場合は、ログを開発者に送り返すこともできます)
  • HTTP Ping
  • (それぞれにHTTP Pingを使用してプロキシ構成を切り替える)
0
Todd