programing

를 사용하여 인터넷 연결을 확인하는 가장 좋은 방법은 무엇입니까?NET?

oldcodes 2023. 5. 4. 20:31
반응형

를 사용하여 인터넷 연결을 확인하는 가장 좋은 방법은 무엇입니까?NET?

에서 인터넷 연결을 확인하는 가장 빠르고 효율적인 방법은 무엇입니까?NET?

이란과 중국에서도 작동하는 이 코드를 사용할 수 있습니다.

public static bool CheckForInternetConnection(int timeoutMs = 10000, string url = null)
{
    try
    {
        url ??= CultureInfo.InstalledUICulture switch
        {
            { Name: var n } when n.StartsWith("fa") => // Iran
                "http://www.aparat.com",
            { Name: var n } when n.StartsWith("zh") => // China
                "http://www.baidu.com",
            _ =>
                "http://www.gstatic.com/generate_204",
        };

        var request = (HttpWebRequest)WebRequest.Create(url);
        request.KeepAlive = false;
        request.Timeout = timeoutMs;
        using (var response = (HttpWebResponse)request.GetResponse())
            return true;
    }
    catch
    {
        return false;
    }
}

인터넷 연결 여부를 안정적으로 확인할 수 있는 방법은 절대 없습니다(인터넷에 대한 액세스를 의미하는 것으로 가정합니다).

그러나 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;
}

확인하는 대신 작업(웹 요청, 메일, 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

네트워크가 다운되면 핑 등과 같은 속도로 작업이 실패합니다.

1 - start to perform action
2 - if the net is down(or goes down) the action will fail

NetworkInterface.GetIsNetworkAvailable매우 신뢰할 수 없습니다.VMware 또는 다른 LAN에 연결하기만 하면 잘못된 결과가 반환됩니다. 에대서도에 도.Dns.GetHostEntrymethod 애플리케이션이 배포될 환경에서 테스트 URL이 차단될 수 있는지 걱정했습니다.

된 또 은 그래제알또방법은다른낸아가서방은법▁using▁so다▁i또▁way른그래▁another제를 사용하는 것입니다.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 google.com 에는 DNS 확인 종속성이 도입됩니다.8.8.8.8구글은 저와 몇 홉 떨어져 있습니다.제가 해야 할 일은 인터넷에 있는 저와 가장 가까운 것을 ping하기만 하면 됩니다.

사용할 수 있습니다Ping라우팅 가능한 주소에 있는 무언가로부터 응답을 받을 때까지 ping #1, 그 다음 hop #2 등에 대한 TTL 기능. 해당 노드가 라우팅 가능한 주소에 있으면 인터넷에 있습니다.대부분의 경우 홉 #1은 로컬 게이트웨이/라우터가 될 것이며 홉 #2는 파이버 연결의 반대쪽에 있는 첫 번째 지점이 될 것입니다.

이 코드는 저에게 효과가 있으며, 인터넷에서 제게 가장 가까운 곳에 있는 모든 것을 ping하기 때문에 이 스레드의 다른 제안보다 빠르게 응답합니다.


using System.Diagnostics;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Threading.Tasks;
    
public static async Task<bool> IsConnectedToInternetAsync()
{
    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++)
    {
        var options = new PingOptions(ttl, true);
        byte[] buffer = new byte[32];
        PingReply reply;
        try
        {
            using (var pinger = new Ping())
            {
                reply = await pinger.SendPingAsync(someFarAwayIpAddress, 10000, buffer, options);
            }
        }
        catch (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;
        }
    
        string address = reply.Address?.ToString() ?? null;
        Debug.Print($"Hop #{ttl} is {address}, {reply.Status}");
    
        if (reply.Status != IPStatus.TtlExpired && reply.Status != IPStatus.Success)
        {
            Debug.Print($"Hop #{ttl} is {reply.Status}, hence we are not connected.");
            return false;
        }
    
        if (IsRoutableAddress(reply.Address))
        {
            Debug.Print("That's routable, so we 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;
        }
    }
}

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

네트워크인터페이스

if 사용 가능인터넷 사용 가능) 반품하기True

if할 수 없고 되어 있음) (인터넷 사용 불가 및 네트워크 케이블 연결됨)True

if되지 않음)(네트워크 케이블이 연결되지 않음)false

[dll 가져오기("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;
}

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

예외를 포착하여 연결을 테스트하지 않도록 합니다.왜냐하면 우리는 때때로 네트워크 연결이 끊길 수도 있다고 정말로 기대하기 때문입니다.

 if (NetworkInterface.GetIsNetworkAvailable() &&
     new Ping().Send(new IPAddress(new byte[] { 8, 8, 8, 8 }),2000).Status == IPStatus.Success)
 //is online
 else
 //is offline

저는 그것이 불가능하다고 생각하지 않습니다. 그냥 간단하지 않습니다.

저는 이런 것을 만들었습니다. 네, 완벽하지는 않지만, 첫 번째 단계는 네트워크 연결이 있는지 확인하는 것입니다.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;
}

이 방법은 매우 간단하지만 특히 다양한 프록시 구성을 확인하려는 경우 검사 품질을 향상시키는 데 큰 도움이 됩니다.

그래서:

  • 네트워크 연결이 있는지 확인합니다(네트워크 사용 가능 기능을 개선하기 위해 잘못된 긍정이 있을 때 로그를 개발자가 다시 보낼 수도 있음).
  • HTTP Ping
  • (각각 HTTP Ping이 있는 프록시 구성을 순환)

소개

일부 시나리오에서는 Windows 응용 프로그램에서 C# 코드를 사용하여 인터넷을 사용할 수 있는지 여부를 확인해야 합니다.Windows 양식에서 인터넷을 사용하여 파일을 다운로드하거나 업로드하거나 원격 위치에 있는 데이터베이스에서 일부 데이터를 가져오려면 인터넷 검사가 필수적입니다.

코드 뒤에 있는 C#을 사용하여 인터넷 사용 가능 여부를 확인하는 몇 가지 방법이 있습니다.이러한 모든 방법은 제한 사항을 포함하여 여기에 설명되어 있습니다.

  1. 인터넷 연결 상태(위니트)

'wininet' API를 사용하여 로컬 시스템에 인터넷 연결이 활성화되어 있는지 확인할 수 있습니다.이에 사용되는 네임스페이스는 'System'입니다.런타임.InteropServices'를 사용하고 DllImport를 사용하여 dll 'wininet.dll'을 가져옵니다.그런 다음 예제와 같이 두 매개 변수 설명과 reservedValue가 있는 함수 이름 InternetGetConnectedState를 가진 외부 정적 부울 변수를 만듭니다.

참고: 외부 수식어는 외부에서 구현되는 메서드를 선언하는 데 사용됩니다.외부 한정자는 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;
    }
}
  1. GetIs 네트워크 사용 가능

다음 예제에서는 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

Ping 및 PingReply 클래스를 사용하면 응용 프로그램에서 호스트로부터 응답을 받아 네트워크를 통해 원격 컴퓨터에 액세스할 수 있는지 여부를 확인할 수 있습니다.이러한 클래스는 시스템에서 사용할 수 있습니다.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이 성공하면 네트워크에서 원격 호스트에 연결할 수 있음만 나타내며, 원격 호스트에 웹 서버와 같은 상위 수준의 서비스가 있을 수 없습니다.

의견/제안을 초대합니다.해피 코딩...!

또 다른 옵션은 Vista 및 Windows 7에서 사용할 수 있는 Network List Manager API입니다. MSDN 문서는 여기에 있습니다.이 문서에는 다음 작업을 수행할 수 있는 코드 샘플 다운로드 링크가 나와 있습니다.

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

COM 탭에서 Network List 1.0 Type Library에 대한 참조를 추가해야 합니다...네트워크 목록으로 표시됩니다.

저는 개인적으로 Anton과 moffelje의 답변이 가장 좋다고 생각하지만, 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));
}

승인된 답변은 빠르게 성공하지만 연결이 없을 때 실패하는 속도가 매우 느립니다.그래서 저는 더 빨리 실패할 수 있는 강력한 연결 검사를 구축하고 싶었습니다.

모든 환경에서 Ping이 지원되지 않는다고 해서 승인된 답변으로 시작하여 사용자 지정 시간 제한이 있는 WebClient를 여기에서 추가했습니다.타임아웃은 아무 때나 선택할 수 있지만, 와이파이로 연결되는 동안 저는 3초가 작동했습니다.빠른 반복(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;
    }
}

네트워크/연결이 변경될 때마다 사용자에게 알리거나 조치를 취하려는 경우.
NLM API 사용:

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;
    }
}
bool bb = System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable();

if (bb == true)
    MessageBox.Show("Internet connections are available");
else
    MessageBox.Show("Internet connections are not available");

다중 스레드 버전의 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";
          }
      }
  }

@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로도 대체가 가능하기 때문입니다.

네트워크 모니터를 사용하여 네트워크 상태 및 인터넷 연결을 모니터링합니다.

샘플:

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

나의 애플리케이션을 위해 우리는 또한 작은 파일을 다운로드하여 테스트합니다.

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

저는 인터넷 연결을 위한 세 가지 테스트가 있습니다.

  • 언급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;
    }
}

테스트 수행

만약 당신이DictionaryString그리고.Boolean불렀다CheckList각 테스트의 결과를 다음에 추가할 수 있습니다.CheckList.

자, 각각을 반복합니다.KeyValuePair사용for...each고리.

한다면CheckList포함Valuetrue그러면 인터넷 연결이 있다는 것을 알 수 있습니다.

public static bool HasConnection()
{
    try
    {
        System.Net.IPHostEntry i = System.Net.Dns.GetHostEntry("www.google.com");
        return true;
    }
    catch
    {
        return false;
    }
}

효과가 있습니다.

언급URL : https://stackoverflow.com/questions/2031824/what-is-the-best-way-to-check-for-internet-connectivity-using-net

반응형