Проверка интернет-соединения с помощью HttpWebRequest

Я разрабатываю приложение, которое должно вызывать API отдыха. Приложение должно проверить, есть ли подключение к Интернету, прежде чем выполнять HttpWebRequest. На данный момент я использую приведенный ниже код, чтобы проверить, доступен ли Интернет:

var request = (HttpWebRequest) WebRequest.Create("http://www.google.co.uk");
response = (HttpWebResponse) request.GetResponse();
if (response.StatusCode == HttpStatusCode.OK)
{

   //there is internet

}

Приведенный выше код работает, но иногда я получаю статус HTTP 302 (Найдено).

Есть ли лучший способ проверить, доступно ли подключение к Интернету?


person Massimiliano Peluso    schedule 08.05.2014    source источник
comment
Просто отметим, что HttpWebResponse поступают с веб-серверов. Поэтому, если вы вообще получаете какой-либо ответ, вы должны быть в Интернете. Неважно, какой будет ответ.   -  person Icemanind    schedule 09.05.2014
comment
В связи с этим, если соединение не удается, request.GetResponse() выдает исключение, так что вам понадобится try-catch вместо этого простого «если».   -  person Nyerguds    schedule 12.08.2015


Ответы (2)


Я бы сделал как пинг, ибо двусмысленности нет. Вы либо получите ответ на пинг, либо нет. Кроме того, вы тратите 32 байта, чтобы проверить это, по сравнению с получением домашней страницы Google, которая, если вы посмотрите исходный код, представляет собой много данных:

public bool IsOnline() {
    var ping = new Ping();
    string host = "google.com";
    byte[] buffer = new byte[32];
    int timeout = 1000;
    var pingOptions = new PingOptions();
    PingReply reply = ping.Send(host, timeout, buffer, pingOptions);
    if (reply.Status == IPStatus.Success) {
      return true;
    }
    return false;
}

ИЗМЕНИТЬ

Вот класс, который будет выполнять пинг, используя необработанные низкоуровневые сокеты, и он работает в .NET MF!

public class RawSocketPing
{
    public Socket pingSocket;             // Raw socket handle
    public int pingTtl;                // Time-to-live value to set on ping
    public ushort pingId;                 // ID value to set in ping packet
    public ushort pingSequence;           // Current sending sequence number
    public int pingPayloadLength;      // Size of the payload in ping packet
    public int pingCount;              // Number of times to send ping request
    public int pingReceiveTimeout;     // Timeout value to wait for ping response
    private IPEndPoint destEndPoint;           // Destination being pinged
    public IPEndPoint responseEndPoint;       // Contains the source address of the ping response
    public EndPoint castResponseEndPoint;   // Simple cast time used for the responseEndPoint
    private byte[] pingPacket;             // Byte array of ping packet built
    private byte[] pingPayload;            // Payload in the ping packet
    private byte[] receiveBuffer;          // Buffer used to receive ping response
    private IcmpHeader icmpHeader;             // ICMP header built (for IPv4)
    private DateTime pingSentTime;       // Timestamp of when ping request was sent

    /// <summary>
    /// Base constructor that initializes the member variables to default values. It also
    /// creates the events used and initializes the async callback function.
    /// </summary>
    public RawSocketPing()
    {
        pingSocket = null;
        pingTtl = 8;
        pingPayloadLength = 8;
        pingSequence = 0;
        pingReceiveTimeout = 2000;
        destEndPoint = new IPEndPoint(IPAddress.Loopback, 0);
        icmpHeader = null;

    }

    /// <summary>
    /// Constructor that overrides several members of the ping packet such as TTL,
    /// payload length, ping ID, etc.
    /// </summary>
    /// <param name="af">Indicates whether we're doing IPv4 or IPv6 ping</param>
    /// <param name="ttlValue">Time-to-live value to set on ping packet</param>
    /// <param name="payloadSize">Number of bytes in ping payload</param>
    /// <param name="sendCount">Number of times to send a ping request</param>
    /// <param name="idValue">ID value to put into ping header</param>
    public RawSocketPing(
        int ttlValue,
        int payloadSize,
        int sendCount,
        ushort idValue
        )
        : this()
    {
        pingTtl = ttlValue;
        pingPayloadLength = payloadSize;
        pingCount = sendCount;
        pingId = idValue;

    }

    /// <summary>
    /// This routine is called when the calling application is done with the ping class.
    /// This routine closes any open resource such as socket handles.
    /// </summary>
    public void Close()
    {
        try
        {

            if (pingSocket != null)
            {
                pingSocket.Close();
                pingSocket = null;
            }
        }
        catch (Exception err)
        {

            throw;
        }
    }

    /// <summary>
    /// Since ICMP raw sockets don't care about the port (as the ICMP protoocl has no port
    /// field), we require the caller to just update the IPAddress of the destination 
    /// although internally we keep it as an IPEndPoint since the SendTo method requires
    /// that (and the port is simply set to zero).
    /// </summary>
    public IPAddress PingAddress
    {
        get
        {
            return destEndPoint.Address;
        }
        set
        {
            destEndPoint = new IPEndPoint(value, 0);
        }
    }

    /// <summary>
    /// This routine initializes the raw socket, sets the TTL, allocates the receive
    /// buffer, and sets up the endpoint used to receive any ICMP echo responses.
    /// </summary>
    public void InitializeSocket()
    {
        IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, 0);

        // Create the raw socket

        pingSocket = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.Icmp);

        // Socket must be bound locally before socket options can be applied

        pingSocket.Bind(localEndPoint);

        pingSocket.SetSocketOption(
            SocketOptionLevel.IP,
            SocketOptionName.IpTimeToLive,
            pingTtl
            );

        // Allocate the buffer used to receive the response
        pingSocket.ReceiveTimeout = pingReceiveTimeout;     
        receiveBuffer = new byte[540];
        responseEndPoint = new IPEndPoint(IPAddress.Any, 0);
        castResponseEndPoint = (EndPoint)responseEndPoint;
    }

    /// <summary>
    /// This routine builds the appropriate ICMP echo packet depending on the
    /// protocol family requested.
    /// </summary>
    public void BuildPingPacket()
    {
        // Initialize the socket if it hasn't already been done

        if (pingSocket == null)
        {
            InitializeSocket();
        }

        // Create the ICMP header and initialize the members

        icmpHeader = new IcmpHeader() 
            { Id = pingId, Sequence = pingSequence, Type = IcmpHeader.EchoRequestType, Code = IcmpHeader.EchoRequestCode };

        // Build the data payload of the ICMP echo request

        pingPayload = new byte[pingPayloadLength];

        for (int i = 0; i < pingPayload.Length; i++)
        {
            pingPayload[i] = (byte)'e';
        }
    }

    /// <summary>
    /// This function performs the actual ping. It sends the ping packets created to
    /// the destination 
    /// </summary>
    public bool DoPing()
    {
        bool success = false;

        // Send an echo request
        while (pingCount > 0)
        {
            try
            {
                pingCount--;
                // Increment the sequence count in the ICMP header
                icmpHeader.Sequence = (ushort)(icmpHeader.Sequence + (ushort)1);

                // Build the byte array representing the ping packet. This needs to be done
                //    before ever send because we change the sequence number (which will affect
                //    the calculated checksum).
                pingPacket = icmpHeader.BuildPacket(pingId, pingPayload);

                // Mark the time we sent the packet
                pingSentTime = DateTime.Now;

                // Send the echo request
                pingSocket.SendTo(pingPacket, destEndPoint);
                int Brecieved = pingSocket.ReceiveFrom(
                    receiveBuffer,
                    0,
                    receiveBuffer.Length,
                    SocketFlags.None,
                    ref castResponseEndPoint
                    );

                //IF you get to here, then you got a response.
                success = true;
                break;

            }
            catch (SocketException  err)
            {
                //PING FAILED, try it again for remaining ping counts
            }
        }
        return success;    
    }


}

Вот источник этого кода.

person Icemanind    schedule 08.05.2014
comment
Ping() недоступен в .net Microframework. - person Massimiliano Peluso; 09.05.2014
comment
@MassimilianoPeluso - посмотрите на мой исправленный ответ. - person Icemanind; 09.05.2014
comment
Завтра попробую и сообщу. Спасибо - person Massimiliano Peluso; 09.05.2014
comment
Я использую МФ. Какую ссылку мне нужно добавить в мой проект, чтобы получить доступ к классу IcmpHeader, который вы объявили в своем примере? - person Bill Greer; 23.04.2015
comment
Класс IcmpHeader не найден — я обыскал все сборки в netmf 4.3 и не смог его найти. Не могли бы вы поделиться? - person Shane; 22.08.2016

Используйте обычную обработку исключений try-catch, если вам не нужен другой статус, например 503 и т. д.

        try
        {
            using (WebClient client = new WebClient())
            {
                string htmlCode = client.DownloadString("https://worldtimeapi.org/api/timezone/EST");                    
            }
        }
        catch
        {
            //No Internet 
            Console.WriteLine("No Internet")
        }
person Naresh Bisht    schedule 01.02.2021