https://andrewbaker.ninja/wp-content/themes/twentysixteen/fonts/merriweather-plus-montserrat-plus-inconsolata.css

👁0views
How to Ping a computer using .NET Sockets

CloudScale SEO — AI Article Summary
What it isThis article explains how to implement ICMP ping functionality in .NET applications using socket programming instead of the built-in Ping class.
Why it mattersDevelopers can gain more control over network diagnostics and create custom ping implementations that work in restricted environments or when the standard Ping class doesn't meet specific requirements.
Key takeawayUsing raw sockets for ping gives you more control but requires understanding ICMP protocol details and proper error handling.
///
/// The main entry point for the application.
///
[STAThread]

static void Main(string[] args)
{

    int timeToReplyMs = Ping("andrewbaker.ninja", 10000);
    Console.WriteLine("Time Taken(ms): " + timeToReplyMs);
}




#region Ping Method
///
/// Pings a host and returns the time taken for the host to respond (given the host name or IP address of the host to ping).
///



/// The host (machine name or IP address) to ping.
/// The ping timeout in ms (zero represents infinite).
/// Returns the time in milliseconds to receive a response from the host.

public static int Ping(string host, int timeout)

{

    //IPHostEntry ipHost = Dns.GetHostByName(host);
    IPHostEntry ipHost = Dns.GetHostEntry(host);

    // Ping the server
    return Ping(ipHost, timeout);

}




///
/// Pings a host and returns the time taken for the host to respond.
///




/// The host to ping.
/// The ping timeout in ms (zero represents infinite).
/// Returns the time in milliseconds to receive a response from the host.

public static int Ping(IPHostEntry host, int timeout)

{

    // Declare some Constant Variables
    const int SOCKET_ERROR = -1;
    const int ICMP_ECHO = 8;
    int timeTaken;



    // Declare the IPHostEntry
    if (host == null)
    {
        throw new ArgumentNullException("host", "The host to ping must be specified.");
    }

    Socket socket = null;

    try

    {
        // Initilize a Socket of the Type ICMP
        socket = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.Icmp);


        // Convert to the first Ip address from the host to an endpoint
        IPEndPoint ipepServer = new IPEndPoint(_GetValidAddress(host.AddressList), 0);
        EndPoint epServer = (ipepServer);

        // Set the receiving endpoint to the client machine
        IPHostEntry localHost;

        localHost = Dns.GetHostEntry(Dns.GetHostName());
        IPEndPoint ipEndPointFrom = new IPEndPoint(_GetValidAddress(localHost.AddressList), 0);
        EndPoint EndPointFrom = (ipEndPointFrom);


        int packetSize;

        IcmpPacket packet = new IcmpPacket();

        // Construct the echo packet
        packet.Type = ICMP_ECHO; //8
        packet.SubCode = 0;
        packet.CheckSum = UInt16.Parse("0");
        packet.Identifier = UInt16.Parse("45");
        packet.SequenceNumber = UInt16.Parse("0");

        int pingDataSize = 32; // sizeof(IcmpPacket) - 8;

        packet.Data = new Byte[pingDataSize];

        // Initilize the Packet.Data
        for (int i = 0; i < pingDataSize; i++)
        {
            packet.Data[i] = (byte)'#';
        }

        // Variable to hold the total Packet size
        packetSize = pingDataSize + 8;
        Byte[] icmpPacketBuffer = new Byte[packetSize];
        int totalPacketSize;


        // Call Serialize, which counts the total number of Bytes in the Packet
        totalPacketSize = _SerializePacket(packet, icmpPacketBuffer, packetSize, pingDataSize);


        // Error in Packet Size
        if (totalPacketSize == -1)
        {
            // Throw serialization exception
            throw new ApplicationException("Error serializing packet buffer");
        }

        // Get the packet into a UInt16 array
        // Get the Half size of the Packet
        Double packetSizeDouble = Convert.ToDouble(totalPacketSize);
        Double halfPacketSizeDouble = Math.Ceiling(packetSizeDouble / 2);
        int checkSumBufferLength = Convert.ToInt32(halfPacketSizeDouble);

        // Create a Byte Array
        UInt16[] checkSumBuffer = new UInt16[checkSumBufferLength];

        // Code to initilize the Uint16 array
        int icmpHeaderBufferIndex = 0;

        for (int i = 0; i < checkSumBufferLength; i++)
        {
            checkSumBuffer[i] = BitConverter.ToUInt16(icmpPacketBuffer, icmpHeaderBufferIndex);
            icmpHeaderBufferIndex += 2;

        }

        // Call a method which will return a checksum
        UInt16 unsignedCheckSum = _CalcChecksum(checkSumBuffer, checkSumBufferLength);

        // Save the checksum to the Packet
        packet.CheckSum = unsignedCheckSum;

        // Have the checksum, serialize the packet again
        Byte[] sendbuf = new Byte[packetSize];

        // Check the packet size
        totalPacketSize = _SerializePacket(packet, sendbuf, packetSize, pingDataSize);


        if (totalPacketSize == -1)
        {
            // Throw serialization exception
            throw new ApplicationException("Error serializing packet buffer");

        }


        // Start timing
        int dwStart = Environment.TickCount;

        // Send the Packet
        if (socket.SendTo(sendbuf, packetSize, 0, epServer) == SOCKET_ERROR)
        {
            throw new ApplicationException("Failed to send packet to " + host.HostName + ".");

        }


        // Initialize the buffers. The receive buffer is the size of the
        // ICMP header plus the IP header (20 bytes)
        Byte[] arrayBytesReceived = new Byte[256];


        // Loop for checking the time of the server responding
        while (true)

        {

            int nBytes = socket.ReceiveFrom(arrayBytesReceived, 256, 0, ref EndPointFrom);
            timeTaken = Environment.TickCount - dwStart;



            if (nBytes == SOCKET_ERROR)
            {

                throw new ApplicationException("Failed to receive response to echo packet from " + host.HostName + ".");

            }

            else if (nBytes > 0)

            {
                // Received message
                // int dwStop = Environment.TickCount - dwStart;
                // Console.WriteLine("Reply from " + epServer.ToString() + " in " + dwStop + "MS :Bytes Received" + nBytes);
                break;
            }




            // Default to a one second timeout
            if (timeTaken > timeout && timeout > 0)
            {
                throw new ApplicationException("Ping to " + host.HostName + " timed out after " + timeout + " milliseconds.");
            }
        }

    }
    finally
    {
        if (socket != null)
        {
            // close the socket
            socket.Shutdown(SocketShutdown.Both);
            socket.Close();
        }

    }




    return timeTaken;

}

//
// Find a valid IP address
private static IPAddress _GetValidAddress(IPAddress[] addressList)
{
    for (int i = 0; i < addressList.Length; i++)
    {
        try
        {
            var address = addressList[i].Address;
        }
        catch (Exception)
        {
            // Invalid address
            continue;
        }
        // The address is valid
        return addressList[i];
    }
    return null;
}



#region Private Methods

///
/// This method get the Packet and calculates the total size
/// of the Pack by converting it to byte array
///
private static int _SerializePacket(IcmpPacket packet, Byte[] Buffer, int PacketSize, int PingData)

{

    int cbReturn;

    // serialize the struct into the array
    int Index = 0;


    Byte[] b_type = new Byte[1];
    b_type[0] = (packet.Type);

    Byte[] b_code = new Byte[1];
    b_code[0] = (packet.SubCode);

    Byte[] b_cksum = BitConverter.GetBytes(packet.CheckSum);
    Byte[] b_id = BitConverter.GetBytes(packet.Identifier);
    Byte[] b_seq = BitConverter.GetBytes(packet.SequenceNumber);


    // Console.WriteLine("Serialize type ");
    Array.Copy(b_type, 0, Buffer, Index, b_type.Length);
    Index += b_type.Length;

    // Console.WriteLine("Serialize code ");
    Array.Copy(b_code, 0, Buffer, Index, b_code.Length);
    Index += b_code.Length;

    // Console.WriteLine("Serialize cksum ");
    Array.Copy(b_cksum, 0, Buffer, Index, b_cksum.Length);
    Index += b_cksum.Length;

    // Console.WriteLine("Serialize id ");
    Array.Copy(b_id, 0, Buffer, Index, b_id.Length);
    Index += b_id.Length;

    Array.Copy(b_seq, 0, Buffer, Index, b_seq.Length);
    Index += b_seq.Length;

    // copy the data
    Array.Copy(packet.Data, 0, Buffer, Index, PingData);

    Index += PingData;

    if (Index != PacketSize/* sizeof(IcmpPacket) */)
    {
        cbReturn = -1;
        return cbReturn;
    }

    cbReturn = Index;
    return cbReturn;
}

///
/// This Method has the algorithm to make a checksum
///
private static UInt16 _CalcChecksum(UInt16[] buffer, int size)

{
    int cksum = 0;
    int counter;

    counter = 0;

    while (size > 0)
    {
        UInt16 val = buffer[counter];
        cksum += Convert.ToInt32(val);
        counter += 1;
        size -= 1;
    }

    cksum = (cksum >> 16) + (cksum & 0xffff);
    cksum += (cksum >> 16);

    return (UInt16)(~cksum);

}

#endregion Private Methods




#region IcmpPacket Class (Private)

///
/// Class that holds the Pack information.
///
private class IcmpPacket
{

    ///
    /// Type of message
    ///
    public Byte Type;

    ///
    /// Type of sub code
    ///
    public Byte SubCode;

    ///
    /// Complement checksum of struct
    ///
    public UInt16 CheckSum;

    ///
    /// Identifier
    ///
    public UInt16 Identifier;

    ///
    /// Sequence number
    ///
    public UInt16 SequenceNumber;

    ///
    /// The data
    ///
    public Byte[] Data;

}

#endregion IcmpPacket Class (Private)

}

endregion

Leave a Reply

Your email address will not be published. Required fields are marked *