Microsoft KB Archive/828993

= How to ping an IP address by using sockets in Visual Basic .NET =

Article ID: 828993

Article Last Modified on 4/19/2007

-

APPLIES TO


 * Microsoft Visual Basic .NET 2003 Standard Edition
 * Microsoft Visual Basic .NET 2002 Standard Edition

-



IN THIS TASK

 * SUMMARY
 * Requirements
 * Declare an ICMP packet structure
 * Define the CPing class
 * Calculate the checksum value
 * Implement the user interface
 * Create a console application
 * REFERENCES



SUMMARY
This step-by-step article describes how to use sockets in Microsoft Visual Basic .NET to ping an Internet Protocol (IP) address. The PING command uses Internet Control Message Protocol (ICMP) to test a network connection. The response time to ping a particular IP address is calculated and displayed. This article uses the System.Net.Sockets API of Visual Basic .NET to ping an IP address.

back to the top

Requirements
This article assumes that you are familiar with the following topics:
 * Programming with Visual Basic .NET
 * Sockets

The following list outlines the recommended hardware, software, network infrastructure, and service packs that you need:
 * Microsoft Windows 2000, Microsoft Windows XP, or Microsoft Windows Server 2003
 * Microsoft Visual Basic .NET

back to the top

Declare an ICMP packet structure
ICMP supports packets that contain error messages, control messages, and informational messages. The PING command uses ICMP to test a network connection. Use the following code to declare the structure of an ICMP packet and to declare a method to calculate the total number of bytes in a packet: Structure IcmpPacket Dim type_message As Byte               ' Type of message. Dim subCode_type As Byte               ' Type of sub-code. Dim complement_checkSum As UInt16      ' One's complement checksum for the structure. Dim identifier As UInt16               ' Identifier. Dim sequenceNumber As UInt16           ' Sequence number. Dim data As Byte                     ' Data.
 * 1) Region &quot;PUBLIC MEMBER VARIABLES&quot;
 * 1) End Region

Public Sub Initialize(ByVal type As Byte, ByVal subCode As Byte, ByVal payload As Byte) Dim index As Integer Dim buffer_icmpPacket As Byte Dim cksumBuffer As UInt16 Dim icmpHeaderBufferIndex As Int32 = 0 Me.type_message = type Me.subCode_type = subCode complement_checkSum = UInt16.Parse(&quot;0&quot;) identifier = UInt16.Parse(&quot;45&quot;) sequenceNumber = UInt16.Parse(&quot;0&quot;) Data = payload
 * 1) Region &quot;PUBLIC MEMBER METHODS&quot;

' Declare a variable to store the total packet size. ' Call the Serialize method to count the total number of bytes in the packet. buffer_icmpPacket = Serialize

' Resize a UInt16 array to half the size of the packet. ReDim cksumBuffer((buffer_icmpPacket.Length \ 2) - 1)

' Initialize the UInt16 array. For index = 0 To (cksumBuffer.Length - 1) cksumBuffer(index) = BitConverter.ToUInt16(buffer_icmpPacket, icmpHeaderBufferIndex) icmpHeaderBufferIndex += 2 Next index

'Call a method that returns a checksum. complement_checkSum = MCheckSum.Calculate(cksumBuffer, cksumBuffer.Length) End Sub

Public Function Size As Integer Return (8 + Data.Length) End Function

' The Serialize method converts the packet to a byte array to calculate the total size. Public Function Serialize As Byte Dim b_seq As Byte = BitConverter.GetBytes(sequenceNumber) Dim b_cksum As Byte = BitConverter.GetBytes(complement_checkSum) Dim b_id As Byte = BitConverter.GetBytes(identifier) Dim index As Int32 = 0 Dim buffer As Byte ReDim buffer(Size - 1)

' Serialize the structure into the array. buffer(0) = type_message buffer(1) = subCode_type index += 2 Array.Copy(b_cksum, 0, buffer, index, 2) index += 2 Array.Copy(b_id, 0, buffer, index, 2) index += 2 Array.Copy(b_seq, 0, buffer, index, 2) index += 2

' Copy the data. If (Data.Length > 0) Then Array.Copy(Data, 0, buffer, index, Data.Length) End If        Return buffer End Function End Structure back to the top
 * 1) End Region

Define the CPing class
The CPing class contains methods to accept the host name or the IP address of a server as input, to ping the host name or IP address, and to display the response time. ' The CPing class. Public Class CPing Private Const DEFAULT_TIMEOUT As Integer = 1000 Private Const SOCKET_ERROR As Integer = -1 Private Const PING_ERROR As Integer = -1 Private Const ICMP_ECHO As Integer = 8 Private Const DATA_SIZE As Integer = 32 Private Const RECV_SIZE As Integer = 128
 * 1) Region &quot;MEMBER CONSTANTS&quot;
 * 1) End Region

Private _open As Boolean = False Private _initialized As Boolean Private _recvBuffer As Byte Private _packet As IcmpPacket Private _hostName As String Private _server As EndPoint Private _local As EndPoint Private _socket As Socket
 * 1) Region &quot;MEMBER VARIABLES&quot;


 * 1) End Region

Public Sub New(ByVal hostName As String) Me.HostName = hostName ReDim _recvBuffer(RECV_SIZE - 1) End Sub
 * 1) Region &quot;CONSTRUCTORS & FINALIZER&quot;

Public Sub New ' Set the default host name to the local host. Me.HostName = Dns.GetHostName ReDim _recvBuffer(RECV_SIZE - 1) End Sub

Private Overloads Sub finalize ' Make sure that you close the socket. Me.Close Erase _recvBuffer End Sub
 * 1) End Region

' Get and set the current host name. Public Property HostName As String Get Return _hostName End Get Set(ByVal Value As String) _hostName = Value ' If the CPing object is already open, close it and then reopen it by using a new host name. If (_open) Then Me.Close Me.Open End If        End Set End Property
 * 1) Region &quot;MEMBER METHODS&quot;

' Get the state (open or closed). Public ReadOnly Property IsOpen As Boolean Get Return _open End Get End Property

' Create a socket to host remote end points and local end points. Public Function Open As Boolean Dim payload As Byte

If (Not _open) Then Try ' Initialize the packet. ReDim payload(DATA_SIZE) _packet.Initialize(ICMP_ECHO, 0, payload)

' Initialize an ICMP socket. _socket = New Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.Icmp)

' Set the server end point. _server = New IPEndPoint(Dns.GetHostByName(_hostName).AddressList(0), 0)

' Set the receiving end point as your client computer. _local = New IPEndPoint(Dns.GetHostByName(Dns.GetHostName).AddressList(0), 0) _open = True Catch Return False End Try End If        Return True End Function

' Destroy the socket and the end points (if necessary). Public Function Close As Boolean If (_open) Then _socket.Close _socket = Nothing _server = Nothing _local = Nothing _open = False End If        Return True End Function

' Perform a PING operation. Public Overloads Function Ping As Integer Return Ping(DEFAULT_TIMEOUT) End Function

' The Ping method performs a PING operation. Public Overloads Function Ping(ByVal timeOutMilliSeconds As Integer) As Integer

' Initialize the time-out value. Dim timeOut As Integer = timeOutMilliSeconds + Environment.TickCount

' Send the packet. If (SOCKET_ERROR = _socket.SendTo(_packet.Serialize, _packet.Size, 0, _server)) Then Return PING_ERROR End If

' Use the following loop to check the response time until you receive a time-out. Do           ' Poll the read buffer every millisecond. ' If data exists, read the data and return the round-trip time. If (_socket.Poll(1000, SelectMode.SelectRead)) Then _socket.ReceiveFrom(_recvBuffer, RECV_SIZE, 0, _local) Return (timeOutMilliSeconds - (timeOut - Environment.TickCount)) ElseIf (Environment.TickCount >= timeOut) Then Return PING_ERROR End If        Loop While (True) End Function End Class back to the top
 * 1) End Region

Calculate the checksum value
The following code contains a Calculate method to calculate the checksum value. This code also contains unions that the Calculate method uses.  _ Structure UNION_INT16  Dim lsb As Byte     ' Least significant byte  Dim msb As Byte     ' Most significant byte  Dim w16 As Short End Structure
 * 1) Region &quot;MEMBER METHODS&quot;

 _ Structure UNION_INT32  Dim lsw As UNION_INT16    ' Most significant word  Dim msw As UNION_INT16    ' Least significant word  Dim w32 As Integer End Structure

' The Calculate method calculates the checksum value. Public Function Calculate(ByRef buffer As UInt16, ByVal size As Int32) As UInt16 Dim counter As Int32 = 0 Dim cksum32 As UNION_INT32 Do While (size > 0) cksum32.w32 += Convert.ToInt32(buffer(counter)) counter += 1 size -= 1 Loop

cksum32.w32 = cksum32.msw.w16 + cksum32.lsw.w16 + cksum32.msw.w16 Return Convert.ToUInt16(cksum32.lsw.w16 Xor &HFFFF) End Function back to the top
 * 1) End Region

Implement the user interface
The following code implements the user interface. This code determines whether the host name or the IP address that the user types is empty, and then alerts the user to type a host name or an IP address in the specified format. After the user types a host name or an IP address, the application establishes a socket connection to the corresponding IP address (if this address is in the same network), and then the application sends a data packet by using ICMP. The application then calculates the time taken (in milliseconds) to send and receive the data packet, and then the application displays this value. If the host name or the IP address is not in the same network or if the user types an invalid IP address or an invalid host name, the application displays a message. Sub Main Dim Packet As New ICMP_Packet.CPing Dim retValue

Console.WriteLine(&quot;Enter the IP address or the host name to ping: &quot;)

' Accept a host name or an IP address. Packet.HostName = Trim(Console.ReadLine)

' Determine whether the user has typed only spaces instead of a host name or an IP address. If Packet.HostName = &quot;&quot; Then Console.WriteLine(&quot;Please enter an IP address (in the N.N.N.N format) or a host name&quot;) Else ' Determine whether you can establish a socket connection to the IP address. If Packet.Open Then ' Establish a socket connection, and then send a packet using ICMP. retValue = Packet.Ping If retValue <> -1 Then ' Display the response time in milliseconds. Console.WriteLine(&quot;Approximate response time : &quot; & retValue) Else Console.WriteLine(&quot;Host Unreachable&quot;) End If     Else Console.WriteLine(&quot;No host found&quot;) End If     Packet.Close

End If

Console.WriteLine(&quot;Press ENTER to quit.&quot;) Console.ReadLine

End Sub back to the top

Create a console application
 Start Microsoft Visual Studio .NET. On the File menu, point to New, and then click Project. The New Project dialog box appears. Under Project Types, click Visual Basic Projects.</li> Under Templates, click Console Application.</li> In the Name box, type MyConsoleApplication.

Note MyConsoleApplication is a sample Visual Basic .NET application.</li> In the Location box, type the location where you want to save the MyConsoleApplication project, and then click OK.

By default, the Module1.vb file is created.</li>  In the Module1.vb file, replace the existing code with the following code: Imports System.Net.Sockets Imports System.Net Imports System Imports System.Runtime.InteropServices

Namespace ICMP_Packet

' Define the structure of an ICMP packet. ' This structure contains packet information. Structure IcmpPacket Dim type_message As Byte               ' type of message Dim subCode_type As Byte               ' type of sub-code Dim complement_checkSum As UInt16      ' one's complement checksum for the structure Dim identifier As UInt16               ' identifier Dim sequenceNumber As UInt16           ' sequence number Dim data As Byte                     ' data
 * 1) Region &quot;PUBLIC MEMBER VARIABLES&quot;
 * 1) End Region

Public Sub Initialize(ByVal type As Byte, ByVal subCode As Byte, ByVal payload As Byte) Dim index As Integer Dim buffer_icmpPacket As Byte Dim cksumBuffer As UInt16 Dim icmpHeaderBufferIndex As Int32 = 0 Me.type_message = type Me.subCode_type = subCode complement_checkSum = UInt16.Parse(&quot;0&quot;) identifier = UInt16.Parse(&quot;45&quot;) sequenceNumber = UInt16.Parse(&quot;0&quot;) Data = payload
 * 1) Region &quot;PUBLIC MEMBER METHODS&quot;

' Declare a variable to store the total packet size. ' Call the Serialize method to count the total number of bytes in the packet. buffer_icmpPacket = Serialize

' Resize a UInt16 array to half the size of the packet. ReDim cksumBuffer((buffer_icmpPacket.Length \ 2) - 1)

' Initialize the UInt16 array. For index = 0 To (cksumBuffer.Length - 1) cksumBuffer(index) = BitConverter.ToUInt16(buffer_icmpPacket, icmpHeaderBufferIndex) icmpHeaderBufferIndex += 2 Next index

'Call a method that returns a checksum. complement_checkSum = MCheckSum.Calculate(cksumBuffer, cksumBuffer.Length) End Sub

Public Function Size As Integer Return (8 + Data.Length) End Function

' The Serialize method converts the packet to a byte array to calculate the total size. Public Function Serialize As Byte Dim b_seq As Byte = BitConverter.GetBytes(sequenceNumber) Dim b_cksum As Byte = BitConverter.GetBytes(complement_checkSum) Dim b_id As Byte = BitConverter.GetBytes(identifier) Dim index As Int32 = 0 Dim buffer As Byte ReDim buffer(Size - 1)

' Serialize the structure into the array. buffer(0) = type_message buffer(1) = subCode_type index += 2 Array.Copy(b_cksum, 0, buffer, index, 2) index += 2 Array.Copy(b_id, 0, buffer, index, 2) index += 2 Array.Copy(b_seq, 0, buffer, index, 2) index += 2

' Copy the data. If (Data.Length > 0) Then Array.Copy(Data, 0, buffer, index, Data.Length) End If        Return buffer End Function End Structure
 * 1) End Region

' The CPing class. Public Class CPing Private Const DEFAULT_TIMEOUT As Integer = 1000 Private Const SOCKET_ERROR As Integer = -1 Private Const PING_ERROR As Integer = -1 Private Const ICMP_ECHO As Integer = 8 Private Const DATA_SIZE As Integer = 32 Private Const RECV_SIZE As Integer = 128
 * 1) Region &quot;MEMBER CONSTANTS&quot;
 * 1) End Region

Private _open As Boolean = False Private _initialized As Boolean Private _recvBuffer As Byte Private _packet As IcmpPacket Private _hostName As String Private _server As EndPoint Private _local As EndPoint Private _socket As Socket
 * 1) Region &quot;MEMBER VARIABLES&quot;


 * 1) End Region

Public Sub New(ByVal hostName As String) Me.HostName = hostName ReDim _recvBuffer(RECV_SIZE - 1) End Sub
 * 1) Region &quot;CONSTRUCTORS & FINALIZER&quot;

Public Sub New ' Set the default host name to the local host. Me.HostName = Dns.GetHostName ReDim _recvBuffer(RECV_SIZE - 1) End Sub

Private Overloads Sub finalize ' Ensure that you close the socket. Me.Close Erase _recvBuffer End Sub
 * 1) End Region

' Get and set the current host name. Public Property HostName As String Get Return _hostName End Get Set(ByVal Value As String) _hostName = Value ' If the CPing object is already open, close it and then reopen it by using a new host name. If (_open) Then Me.Close Me.Open End If        End Set End Property
 * 1) Region &quot;MEMBER METHODS&quot;

' Get the state (open or closed). Public ReadOnly Property IsOpen As Boolean Get Return _open End Get End Property

' Create a socket to host remote end points and local end points. Public Function Open As Boolean Dim payload As Byte

If (Not _open) Then Try ' Initialize the packet. ReDim payload(DATA_SIZE) _packet.Initialize(ICMP_ECHO, 0, payload)

' Initialize an ICMP socket. _socket = New Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.Icmp)

' Set the server end point. _server = New IPEndPoint(Dns.GetHostByName(_hostName).AddressList(0), 0)

' Set the receiving end point as your client computer. _local = New IPEndPoint(Dns.GetHostByName(Dns.GetHostName).AddressList(0), 0) _open = True Catch Return False End Try End If        Return True End Function

' Destroy the socket and end points (if necessary). Public Function Close As Boolean If (_open) Then _socket.Close _socket = Nothing _server = Nothing _local = Nothing _open = False End If        Return True End Function

' Perform a PING operation. Public Overloads Function Ping As Integer Return Ping(DEFAULT_TIMEOUT) End Function

' The Ping method performs a PING operation. Public Overloads Function Ping(ByVal timeOutMilliSeconds As Integer) As Integer

' Initialize the time-out value. Dim timeOut As Integer = timeOutMilliSeconds + Environment.TickCount

' Send the packet. If (SOCKET_ERROR = _socket.SendTo(_packet.Serialize, _packet.Size, 0, _server)) Then Return PING_ERROR End If

' Use the following loop to check the response time until you receive a time-out. Do           ' Poll the read buffer every millisecond. ' If data exists, read the data and return the round-trip time. If (_socket.Poll(1000, SelectMode.SelectRead)) Then _socket.ReceiveFrom(_recvBuffer, RECV_SIZE, 0, _local) Return (timeOutMilliSeconds - (timeOut - Environment.TickCount)) ElseIf (Environment.TickCount >= timeOut) Then Return PING_ERROR End If        Loop While (True) End Function End Class
 * 1) End Region

' The MCheckSum module contains the static Calculate method. Module MCheckSum <StructLayout(LayoutKind.Explicit)> _ Structure UNION_INT16 <FieldOffset(0)> Dim lsb As Byte     ' Least significant byte <FieldOffset(1)> Dim msb As Byte     ' Most significant byte <FieldOffset(0)> Dim w16 As Short End Structure
 * 1) Region &quot;MEMBER METHODS&quot;

<StructLayout(LayoutKind.Explicit)> _ Structure UNION_INT32 <FieldOffset(0)> Dim lsw As UNION_INT16    ' Most significant word <FieldOffset(2)> Dim msw As UNION_INT16    ' Least significant word <FieldOffset(0)> Dim w32 As Integer End Structure

' The Calculate method calculates the checksum value. Public Function Calculate(ByRef buffer As UInt16, ByVal size As Int32) As UInt16 Dim counter As Int32 = 0 Dim cksum32 As UNION_INT32 Do While (size > 0) cksum32.w32 += Convert.ToInt32(buffer(counter)) counter += 1 size -= 1 Loop

cksum32.w32 = cksum32.msw.w16 + cksum32.lsw.w16 + cksum32.msw.w16 Return Convert.ToUInt16(cksum32.lsw.w16 Xor &HFFFF) End Function
 * 1) End Region

Sub Main Dim Packet As New ICMP_Packet.CPing Dim retValue

Console.WriteLine(&quot;Enter the IP address or the host name to ping: &quot;)

' Accept a host name or an IP address. Packet.HostName = Trim(Console.ReadLine)

' Determine whether the user has typed only spaces instead of a host name or an IP address. If Packet.HostName = &quot;&quot; Then Console.WriteLine(&quot;Please enter an IP address (in the N.N.N.N format) or a host name&quot;) Else ' Determine whether you can establish a socket connection to the IP address. If Packet.Open Then ' Establish a socket connection, and then send a packet by using ICMP. retValue = Packet.Ping If retValue <> -1 Then ' Display the response time in milliseconds. Console.WriteLine(&quot;Approximate response time : &quot; & retValue) Else Console.WriteLine(&quot;Host Unreachable&quot;) End If           Else Console.WriteLine(&quot;No host found&quot;) End If           Packet.Close

End If

Console.WriteLine(&quot;Press ENTER to quit.&quot;) Console.ReadLine

End Sub End Module

End Namespace </li> In Solution Explorer, click the MyConsoleApplication project.</li> On the Project menu, click Properties.</li> In the MyConsoleApplication Property Pages dialog box, select Sub Main from the Startup object drop-down list box, and then click OK.</li> On the Debug menu, click Start.</li> At the command prompt that appears, type a host name or an IP address, and then press ENTER.</li></ol>

back to the top

<div class="references_section">