Riples
Riples

Reputation: 1157

What Is The Best Way To Run Continous Pings On Multiple IP Addresses

I have an application that currently runs a ping against about 60 different gateways to monitor internet uptime for my clients as I want to know if their internet drops out before they do. So currently my application runs through a loop starting at the first one (runs 4 pings) waits 2 seconds and then moves on to the next gateway address. I have then implemented some code to retry a number of times if the ping results as a failure as I want to be 100% sure that their connection is down before sending an alert.

The problem with this method is that it takes around 1 or 2 minutes (or sometimes longer) before the same gateway is scanned again, meaning that if the connection was to drop out straight after a ping, I wouldn't know for nearly 2 minutes. I know this sounds miniscule but I would much rather instant alerting to my team so they can act on this immediately.

Therefore, my question is: Would it be better (and what would be the impact) of running 60 separate pings (on different threads maybe) instead of cycling through each one. This way I could run a continuous ping on each gateway at the same time. However, I am worried about performance impact on my application and if it will create too much load on the system.

Any advice would be appreciated. Thanks

EDIT

I have created the following code which works but seems to impact a single processor core heavily and whilst this method works without error, it seems to deem the GUI as in-responsive soon after:

Public Sub PingHost()
    Try
        GatewayScanning = True
        For i As Integer = 0 To Gateways.Count - 1
            Dim t As New Threading.Thread(AddressOf CheckHostOnline)
            t.IsBackground = True
            t.Start(Gateways(i))
        Next

    Catch ex As Exception
        ErrorTrap(ex, "OfflineClientHandler: PingHost()")
    End Try
End Sub

Public Sub CheckHostOnline(ByVal gw As Object)
    Try
        Dim _gateway As Gateway_Object = DirectCast(gw, Gateway_Object)
        Dim pingSender As New Ping()
        Dim options As New PingOptions()
        'Dim averageTime As Integer
        Dim OfflinePingCount As Integer = 0

        ' Use the default Ttl value which is 128,
        ' but change the fragmentation behavior.
        options.DontFragment = False
        options.Ttl = 128

        ' Create a buffer of 32 bytes of data to be transmitted.
        Dim data As String = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
        Dim buffer() As Byte = Encoding.ASCII.GetBytes(data)
        Dim timeout As Integer = 3000

        Do While Not GatewayScanning = False
            Dim reply As PingReply = pingSender.Send(_gateway.Gateway, timeout, buffer, options)

            If reply.Status = IPStatus.Success Then
                Dim resultTime As Integer = GetMs(CInt(reply.RoundtripTime))
                _gateway.Status = "ONLINE"
                _gateway.Result = resultTime
            Else
                OfflinePingCount += 1
                If OfflinePingCount < (My.Settings.OfflinePingCycleNumber * 4) Then
                    _gateway.Status = "TIMEOUT"
                    _gateway.Result = -1
                Else
                    _gateway.Status = "OFFLINE"
                    _gateway.Result = -1
                End If
            End If

            SyncLock class_OfflineGateways
                class_OfflineGateways.UpdateListView(_gateway)
            End SyncLock

            System.Threading.Thread.Sleep(2000)
        Loop
        pingSender.Dispose()

    Catch ex As Exception
        ErrorTrap(ex, "OfflineClientHandler: CheckHostOnline()")
    End Try

End Sub

Upvotes: 0

Views: 2828

Answers (1)

xpda
xpda

Reputation: 15813

One way to do this is to cycle through the 60 IPs on different threads, and require a five-second (or some amount of time) delay before beginning the cycle again.

Another way is to us asynchronous pings instead of separate threads.

Last time I did this, I ended up using a single thread with 10 ms sleep delay between pings. There were too many ping failures whenever I bunched them together, either with threads or asynch pings. I never did figure out whether the problem was on the server end or on the destination network.

Here's a class I used to ping a list of IP addresses. It (and a bunch of other stuff) ran as a service on an ISP server. (I notice I still have the backgroundworker declared, although it's no longer used.)

Imports System.Net
Imports System.Threading
Imports System.Collections.Generic

Class pingGroup
' used to ping each IP in Targets

Public Targets As New List(Of IPAddress)
Public sectorID As Integer
Public nErrors As Integer = 0
Public Timeout As Integer = pingTimeout

Public PingLog As New List(Of String)
Public PingAvg As Integer = -2 ' -2 = uninit, -1 = error, else average ms excluding the slowest
Public PingTime As DateTime

Public pingCount As Integer = 0
Public pingStarts As Integer = 0
Dim msTotal As Integer = 0

Dim WithEvents bkgPing As System.ComponentModel.BackgroundWorker

Public Sub New(ByVal groupSectorID As Integer)
sectorID = groupSectorID
End Sub

Public Sub Ping()
' run a pingtest once, adding the result incrementally

Dim ip As IPAddress
Dim reply As NetworkInformation.PingReply
Dim ms As Integer

PingTime = Now

If PingLog.Count <= 0 Then PingLog.Add(Format(Now, "G") & " Ping Test")

For Each ip In Targets
  Using pPing As New NetworkInformation.Ping
    Try
      pingStarts = pingStarts + 1
      reply = pPing.Send(ip, Timeout)
      If reply.Status = NetworkInformation.IPStatus.Success Then
        ms = reply.RoundtripTime
        pingCount = pingCount + 1
        msTotal = msTotal + ms
        If pingCount > 0 Then PingAvg = msTotal / pingCount
        PingLog.Add(reply.Address.ToString & " " & ms)
      Else
        nErrors = nErrors + 1
        PingLog.Add(Format(Now, "G") & " ---Ping Error: " & ip.ToString & " " & reply.Status.ToString)
        End If

    Catch ex As Exception
      nErrors = nErrors + 1
      PingLog.Add(Format(Now, "G") & " ===Ping Error: " & ip.ToString & " " & ex.Message)
      End Try
    End Using
  Thread.Sleep(10)
  Next ip

End Sub

End Class

Upvotes: 1

Related Questions