none
Check servers are up and get information such as latency and any other information useful for diagnosing network problems / slow network

Answers

  • I see it.

    Try this one then:

    http://www.fls-online.net/VBNet_Forum/06-21-17/Test_ServerTesting_V3.zip


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    That's perfect - just one query, any idea why it is cutting off last characters in that column e.g. in screenshot below L2013 should be L2013) and looking at other rows it is always last letter so .com is showing as .co


    Darren Rose

    Oversight. Here's the corrected version:

    http://www.fls-online.net/VBNet_Forum/06-21-17/Test_ServerTesting_V4.zip


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    • Marked as answer by wingers Wednesday, June 21, 2017 3:04 PM
    Wednesday, June 21, 2017 2:51 PM
  • All progressing really well now

    Noticed one thing though - if I try and export when I have no servers in the list then it just fails to export/save the XML file - no error is thrown

    Would be nice to have an exception for that like we have for others

    I know I can just check count is not 0 before exporting but thought better handled in the class like you have other bits? is this possible?


    Darren Rose

    http://www.fls-online.net/VBNet_Forum/06-24-17/Test_ServerTesting.zip

    This is what I've done: I've made the choice optional with the default being the same as it currently is (no exception thrown):

            ''' <summary>
            ''' A method to export the data to an XML file.
            ''' </summary>
            ''' <param name="filePath">The full path of the file's location.</param>
            ''' <param name="throwIfEmpty">OPTIONAL: A boolean to indicate
            ''' whether or not an exception should be thrown if the server
            ''' count is zero. Default: False.</param>
            ''' <remarks></remarks>
            Public Sub ExportToXML(ByVal filePath As String, _
                                   Optional ByVal throwIfEmpty As Boolean = False)

                Try
                    If String.IsNullOrWhiteSpace(filePath) Then
                        Throw New ArgumentException("The file path cannot be null or empty.")

                    Else
                        Dim fi As New FileInfo(filePath)

                        If fi.Exists Then
                            fi.Delete()
                        End If

                        If Not Utilities.FileDirectoryCanBeWrittenTo(fi.Directory.FullName) Then
                            Throw New UnauthorizedAccessException("You do not have permission to write to this directory.")

                        Else
                            If List.Count > 0 Then
                                Dim xDoc As XElement = _
                                    <TestSettings>
                                        <Overall>
                                            <%= New XElement("TimeOutMilliseconds", _timeOutMilliseconds.ToString) %>
                                            <%= New XElement("TTL_Max", _tTL_Max.ToString) %>
                                            <%= New XElement("AllowFragmentation", _allowFragmentation.ToString) %>
                                            <%= New XElement("TestCount", _testCount.ToString) %>
                                            <%= New XElement("TestFilesDirectory", _testFilesDirectory) %>
                                        </Overall>
                                        <%= From ci As CollectionItems In GetEnumerable() Select _
                                            <Setting>
                                                <%= New XElement("HostName", ci.HostName) %>
                                                <%= New XElement("AliasName", ci.AliasName) %>
                                                <%= New XElement("IPAddress", ci.IpAddress.ToString) %>
                                                <%= New XElement("IsNative", ci.IsNativeIP.ToString) %>
                                                <%= New XElement("Name", ci.Name) %>
                                            </Setting> %>
                                    </TestSettings>

                                xDoc.Save(fi.FullName)
                            Else
                                If throwIfEmpty Then
                                    Throw New ArgumentException("There are no servers in the collection.")
                                End If
                            End If
                        End If
                    End If

                Catch ex As Exception
                    Throw
                End Try

            End Sub


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    • Marked as answer by wingers Sunday, June 25, 2017 4:45 PM
    Saturday, June 24, 2017 3:06 PM

All replies

  • Darren,

    This isn't my forte. I *thought* maybe so with this:

    https://msdn.microsoft.com/en-us/library/system.net.networkinformation.ipstatus(v=vs.110).aspx

    In looking at it now that doesn't appear to be the case though.

    I ran across some information when I was looking through the documentation for that other thread, but I guess I'm mistaken about what I saw.

    If it's to be had, it likely will be in the System.Net.NetworkInformation namespace.

    *****

    Be patient and see if Reed or others might look in. Reed will definitely know.


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Thursday, March 23, 2017 12:26 PM
  • Thursday, March 23, 2017 12:30 PM
  • Yes I think it is in the namespace you mention

    https://msdn.microsoft.com/en-us/library/system.net.networkinformation.pingreply.roundtriptime(v=vs.110).aspx


    Darren Rose

    That's what I saw!

    I knew I'd seen something about it. Be patient and let's see if someone can get you closer to what you want.

    Also, how about remove your message in that other thread. ;-)


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Thursday, March 23, 2017 12:35 PM
  • Yes I think it is in the namespace you mention

    https://msdn.microsoft.com/en-us/library/system.net.networkinformation.pingreply.roundtriptime(v=vs.110).aspx


    Darren Rose

    That's what I saw!

    I knew I'd seen something about it. Be patient and let's see if someone can get you closer to what you want.

    Also, how about remove your message in that other thread. ;-)


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Message removed from other thread

    Okay will wait and see if any other response

    If not should be possible to get that value back in same way as you get status currently to show in the datagridview, a currently retVal = pinger.Send(address).Status gets the status but a similar line like retVal = pinger.Send(address).RoundtripTime could return the other value perhaps


    Darren Rose

    Thursday, March 23, 2017 6:14 PM

  • Message removed from other thread

    Okay will wait and see if any other response

    If not should be possible to get that value back in same way as you get status currently to show in the datagridview, a currently retVal = pinger.Send(address).Status gets the status but a similar line like retVal = pinger.Send(address).RoundtripTime could return the other value perhaps


    Darren Rose

    You've got Dev's grid which is hands down better than the out-of-the-box DataGridView but the idea is the same.

    Honestly I only barely even remember what I did in that other one that you're talking about.


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Thursday, March 23, 2017 6:21 PM
  • Yes I would probably use Dev's control at some point for it, but for starters the basic one will do as only issue with Dev controls is adding extra size due to amount of DLL's it wants to package, so I find for testing I tend to use basic controls and then add Dev later when got basics working

    I will take a look, just not sure how to return two different things using existing code which just returns one using retVal =


    Darren Rose

    Thursday, March 23, 2017 6:23 PM

  • I will take a look, just not sure how to return two different things using existing code which just returns one using retVal =


    Darren Rose

    I can find it somewhere in the abyss of directories, but if you see "retVal" then no doubt that's a function and I set it as the type and set it to null initially (so that it always returns a value).

    What's the type that it's set as? An instance of a class or ... what?


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Thursday, March 23, 2017 6:27 PM

  • I will take a look, just not sure how to return two different things using existing code which just returns one using retVal =


    Darren Rose

    I can find it somewhere in the abyss of directories, but if you see "retVal" then no doubt that's a function and I set it as the type and set it to null initially (so that it always returns a value).

    What's the type that it's set as? An instance of a class or ... what?


    "A problem well stated is a problem half solved.” - Charles F. Kettering


     Dim retVal As Nullable(Of IPStatus) = Nothing


    Darren Rose

    Thursday, March 23, 2017 6:28 PM


  •  Dim retVal As Nullable(Of IPStatus) = Nothing


    Darren Rose

    That does sound familiar now. ;-)

    IPStatus is an enum -- which is a value type -- so "Nothing" will return the default, not null. Setting it to a Nullable(of T) let's me then return Nothing, despite the fact that it's actually a value type that it represents.

    I'd have to see the whole thing or maybe do something from scratch that's more specific to what you want, but in this case it wouldn't be in there if it's not already because that's part of the framework.

    *****

    First though, there's nothing to do until you get an answer to your question about network diagnostics.

    I bet there's a third-party assembly that's out there somewhere that you might want to have a look around for. I won't swear it'll be free, but who knows.


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Thursday, March 23, 2017 6:39 PM


  •  Dim retVal As Nullable(Of IPStatus) = Nothing


    Darren Rose

    That does sound familiar now. ;-)

    IPStatus is an enum -- which is a value type -- so "Nothing" will return the default, not null. Setting it to a Nullable(of T) let's me then return Nothing, despite the fact that it's actually a value type that it represents.

    I'd have to see the whole thing or maybe do something from scratch that's more specific to what you want, but in this case it wouldn't be in there if it's not already because that's part of the framework.

    *****

    First though, there's nothing to do until you get an answer to your question about network diagnostics.

    I bet there's a third-party assembly that's out there somewhere that you might want to have a look around for. I won't swear it'll be free, but who knows.


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Yes that makes sense

    I have spent literally hours today googling and looking to see if any third-party solutions and have found nothing at all to be honest either free or paid for

    But I have found that you can get quite a lot of information from System.Net.NetworkInformation which could possibly be show in a grid or listview for each server/host it pings/checks

    One example I found which is in C# but does at least show what can be retrieved is https://www.codeproject.com/Articles/18908/Simple-Ping-Utility-with-GUI

    Also other examples showing that I could scan an IP range to pick up any active computers as well and then resolve IP to name etc to then show in app - all potentially useful


    Darren Rose

    Thursday, March 23, 2017 7:11 PM


  • Yes that makes sense

    I have spent literally hours today googling and looking to see if any third-party solutions and have found nothing at all to be honest either free or paid for

    But I have found that you can get quite a lot of information from System.Net.NetworkInformation which could possibly be show in a grid or listview for each server/host it pings/checks

    One example I found which is in C# but does at least show what can be retrieved is https://www.codeproject.com/Articles/18908/Simple-Ping-Utility-with-GUI

    Also other examples showing that I could scan an IP range to pick up any active computers as well and then resolve IP to name etc to then show in app - all potentially useful


    Darren Rose

    I find it incredible that there's nothing out there but anyway, let's see what develops when others reply over the next few days.

    About the CodeProject article: You do realize that you can use that, right?

    It's a dotNET assembly.

    Don't believe that we can use dll's that are in C#? Care to guess what DevExpress controls are written in? ;-)


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Thursday, March 23, 2017 7:20 PM
  • Yes I was surprised too as looked at so many different websites and search through places like www.componentsource.com which have lists of all components available and nothing found so far

    Yes I realised I can use that but wanted to create something myself so to speak so like with other projects you have helped with I learn about it as go along, rather than just borrowing someone else's code


    Darren Rose

    Thursday, March 23, 2017 7:38 PM
  • Yes I was surprised too as looked at so many different websites and search through places like www.componentsource.com which have lists of all components available and nothing found so far

    Yes I realised I can use that but wanted to create something myself so to speak so like with other projects you have helped with I learn about it as go along, rather than just borrowing someone else's code


    Darren Rose

    Let's be patient and if you want then I'll try to help.

    This is the time of year when real work tends to be busy for me (springtime plans for summer/fall construction/renovation), so do know that.


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Thursday, March 23, 2017 7:42 PM
  • okay no problem - I completely understand

    Darren Rose

    Thursday, March 23, 2017 7:49 PM
  • Frank

    Unfortunately no responses yet

    Will continue to be patient but just posting to let you know your fls-online site is down - says "Account Suspended" in case you didn't know        


    Darren Rose

    Saturday, March 25, 2017 8:10 PM
  • ... just posting to let you know your fls-online site is down - says "Account Suspended" in case you didn't know        

    Darren Rose

    That's the start of what I said I was going to do: That domain and the web host are going away soon.

    Change ".com" to ".net" and that's where I'm moving to.

    http://www.fls-online.net/VBNet_Forum/

    :)


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Saturday, March 25, 2017 8:14 PM
  • ... just posting to let you know your fls-online site is down - says "Account Suspended" in case you didn't know        


    Darren Rose

    That's the start of what I said I was going to do: That domain and the web host are going away soon.

    Change ".com" to ".net" and that's where I'm moving to.

    http://www.fls-online.net/VBNet_Forum/

    :)


    "A problem well stated is a problem half solved.” - Charles F. Kettering


    nice one thanks - just thought I would say just in case you didn't know :)

    Darren Rose

    Saturday, March 25, 2017 8:16 PM

  • nice one thanks - just thought I would say just in case you didn't know :)

    Darren Rose

    :-)

    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Saturday, March 25, 2017 8:19 PM
  • Hi Frank

    If you have a few moments at some point I would appreciate your help in best way to achieve following:-

    I have a list of IP Addresses / host names and I want to ping them for a set amount of times each and then return the following in a listview on my form

    IP Address / Name (from PingReply.Address.ToString if successful or from the address passed value if not)

    Status (from PingReply.Status)

    Latency (from PingReply.RoundTripTime) - average / min / max

    I can do it easily enough so it just pings once and shows results - as per code below - (I know probably not done in the best way :) )

    But I want to be able to loop and ping say 10 times, add the PingReply.RoundTripTime to a list so I can then show average, max and min for each IP address in my list

    I suspect you will suggest a class as best way to accomplish this?

    Thanks

    Imports System.Net.NetworkInformation
    Imports System.Text
    
    Public Class Form1
    
        Dim PingAddresses As New List(Of String)
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    
            ' configure form
            ListView1.View = View.Details
            ListView1.FullRowSelect = True
            ListView1.GridLines = True
            ListView1.Columns.Add("Address", 150)
            ListView1.Columns.Add("Status", 100)
            ListView1.Columns.Add("Latency", 100)
    
            ' add to list of addresses to test
            PingAddresses.Add("www.bbc.co.uk")
            PingAddresses.Add("www.pcassistonline.co.uk")
            PingAddresses.Add("www.fgfgf.co.uk")
    
            ' perform tests
            For Each Address In PingAddresses
                Dim PingResult = GetPingResult(Address)
            
                Dim listViewInformation(2) As String
                listViewInformation(0) = PingResult.Address.ToString()
                listViewInformation(1) = PingResult.Status
                listViewInformation(2) = PingResult.Latency
                Dim item As ListViewItem = New ListViewItem(listViewInformation)
                ListView1.Items.Add(item)
    
                If PingResult.Status <> "Success" Then
                    item.ForeColor = Color.Red
                End If
    
            Next
    
        End Sub
    
        Public Class PingResults
            Public Address As String
            Public Status As String
            Public Latency As Integer
        End Class
    
        Public Shared Function GetPingResult(ByVal hostNameOrAddress As String) As PingResults
    
            Dim pr = New PingResults()
    
            Dim Data As String = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
            Dim Buffer As Byte() = Encoding.ASCII.GetBytes(Data)
            Dim Timeout As Integer = 120
            Dim Options As New PingOptions()
            Options.DontFragment = True
    
            Dim Result As Net.NetworkInformation.PingReply
            Dim SendPing As New Net.NetworkInformation.Ping
            Try
                Result = SendPing.Send(hostNameOrAddress, Timeout, Buffer, Options)
    
                pr.Address = Result.Address.ToString
                pr.Status = Result.Status.ToString
                pr.Latency = Result.RoundtripTime
    
            Catch ex As Exception
    
                pr.Address = hostNameOrAddress
                pr.Status = "Failed"
                pr.Latency = 0
    
            End Try
    
            Return pr
    
        End Function
    
    End Class
    


    Darren Rose

    Tuesday, March 28, 2017 2:29 PM
  • Darren,

    I'll look at this later - either this afternoon or later this week.


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Tuesday, March 28, 2017 2:48 PM
  • Darren,

    Let's talk some about this - right now I'll try to get my head into what's needed and I'll work on it over the next few days as I can.

    I'd first like to comment some about the function you have:

    Public Shared Function GetPingResult(ByVal hostNameOrAddress As String) As PingResults Dim pr = New PingResults() Dim Data As String = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" Dim Buffer As Byte() = Encoding.ASCII.GetBytes(Data) Dim Timeout As Integer = 120 Dim Options As New PingOptions() Options.DontFragment = True Dim Result As Net.NetworkInformation.PingReply Dim SendPing As New Net.NetworkInformation.Ping Try Result = SendPing.Send(hostNameOrAddress, Timeout, Buffer, Options) pr.Address = Result.Address.ToString pr.Status = Result.Status.ToString pr.Latency = Result.RoundtripTime Catch ex As Exception pr.Address = hostNameOrAddress pr.Status = "Failed" pr.Latency = 0 End Try Return pr End Function


    There's no good reason to have it shared (it's an instance method) but that's not the point that I want to make.

    Are you familiar with "late binding"? It slows the process down and really should be avoided by refactoring the code.

    If you'll set Option Strict On, you'll see what all it shows as being an issue but it comes down to this one line:

    Dim pr = New PingResults()

    Tell me this please: What [type] is the variable "pr"?

    Answer: You don't know. We can infer that it's a PingResults - so does the compiler - but that's late binding and when we get to these:

    pr.Address = Result.Address.ToString
    pr.Status = Result.Status.ToString
    pr.Latency = Result.RoundtripTime

    That's where it sees that you're asking it to a lot of guessing.

    Think about it, you're telling it "I'm not going to tell you what it is, but I want you to set the following fields to this, that and the other anyway. Just take my word on it!"

    Little wonder it balks. ;-)

    One small change will matter a lot:

    Dim pr As PingResults = New PingResults()

    Now it knows the type.

    *****

    Starting from the start here,

    I have a list of IP Addresses / host names and I want to ping them for a set amount of times each and then return the following in a listview on my form

    I'll return data that you can use, but don't confuse the data with the presentation of it.

    We can talk later about how to do that, but can you show me an example of what you'd give it? Will it always be URL's like you show here or just what? Also, the "set amount of runs" - is that something for all of of them or individually? Should this information be persisted to file or will you be giving it this information each time?


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Tuesday, March 28, 2017 4:57 PM
  • Hi Frank

    Yes I know what late binding is - and now I have turned Option Strict On I can see it showing me a couple of issues - I really should remember to turn that on before I do anything! :)

    To be honest it didn't actually highlight any problem with the line you mentioned, but it did show me Latency needed to be declared as a Long rather than an Integer and that it then needed converting to a string to show it in the listview

    ------

    Okay that's fine

    I will give it a list of mainly IP addresses, occasionally a website, but mainly internal IP addresses of servers etc - so it would just be 192.168.10.2, 192.168.20.4 etc etc, probably in the range of about 20-30 addresses.  Sometimes might get it to check external website as well so would be in format of www.pcassistonline.co.uk but could give it the IP of website instead of needed

    I was just using URL's for now as a test to get data back

    The list of IP's would either be hard coded in - or better still just a file it could read them from, so can easily amend it later

    The set amount of runs would be for all of them, but now you have said it then it might be handy to be able to change individually in some cases, but mainly a set amount for all of them, just long enough to be able to generate .max .min and .average for them

    Hope that covers your questions - if not please let me know

    Other than doing the job I need I am hoping from doing this with you I will learn to build a class from scratch and do things the right way in future - so perhaps I can end up with a skeleton class as well that I can then use/modify for future projects - then I won't need to keep asking for help!!! :)


    Darren Rose

    Tuesday, March 28, 2017 5:16 PM
  • The information returned by Ping is a good indicator of packet transmission time, but it is important to note that "Round Trip Time" is not the same as Latency since Latency is a measurement of a single transmission in a single direction and the round trip includes both sending the echo packet and receiving the response.  So round trip time is the sum of two latencies.  It isn't safe to assume that you can divide the round trip time in half to get the latency because it could be different in one direction versus the other... the transmitted packet could take a different route than the response packet.

    It is also worth noting that ICMP traffic may be treated differently on a given network (or network segment) than IP or UDP traffic, so the time it takes to send a ping request and get a reply may not be indicative of the speed at which the remote host is capable of responding.  For example, a file hosting network might route ICMP traffic over a lower priority causing minor delays in ping responses which would not be present in an actual IP stream file transfer.

    So bearing that information in mind, you can get a rough idea of a remote host's availability and response time by repeatedly pinging it and aggregating the results.  Another worthy point of notice is that repeated pings to the same address can be seen as an attempted Denial-of-Service (DoS) attack by firewalls and other security software/appliances, so you should limit the rate at which you ping remote hosts.

    Here is an example of a small class to hold ping statistics with an IP address, a class to monitor a list of addresses, and an example form showing use the other two classes.

    Imports System.Net Imports System.Net.NetworkInformation Public Class Form1 Friend WithEvents StartButton As New Button With {.AutoSize = True, .Dock = DockStyle.Top, .Text = "Start Monitor"} Friend WithEvents StopButton As New Button With {.AutoSize = True, .Dock = DockStyle.Top, .Text = "STop Monitor"} Friend WithEvents ListBox1 As New ListBox With {.Dock = DockStyle.Fill} Private addresses As New List(Of IPAddress) Private WithEvents monitor As New IpAddressMonitor Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load Controls.Add(ListBox1) Controls.Add(StopButton) Controls.Add(StartButton) addresses.Add(IPAddress.Parse("8.8.8.8")) addresses.Add(Dns.GetHostAddresses("www.msn.com")(0)) addresses.Add(Dns.GetHostAddresses("www.bing.com")(0)) For Each address In addresses monitor.Add(address) Next End Sub Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles StartButton.Click Try StartButton.Enabled = False Await monitor.BeginMonitoring Catch ex As Exception Stop Finally StartButton.Enabled = True End Try End Sub Private Sub Button2_Click(sender As Object, e As EventArgs) Handles StopButton.Click monitor.StopMonitoring() End Sub Private Sub monitor_StatisticsUpdated(sender As Object, e As EventArgs) Handles monitor.StatisticsUpdated If InvokeRequired Then Invoke(Sub() monitor_StatisticsUpdated(sender, e) End Sub) Else ListBox1.BeginUpdate() ListBox1.Items.Clear() For Each address In addresses Dim stats = monitor.Item(address) ListBox1.Items.Add($"{stats.Address}: Available = {stats.Available}, Success Rate = {stats.SuccessRate:p0}") ListBox1.Items.Add($"Round Trip: Min = {stats.MinRoundTrip}, Max = {stats.MaxRoundTrip}, Avg = {stats.AverageRoundTrip}") ListBox1.Items.Add(String.Empty) Next ListBox1.EndUpdate() End If End Sub End Class Public Class IpAddressMonitor Implements ICollection(Of IPAddress) Protected Shared bufferData() As Byte = (From i In Enumerable.Range(0, 32) Select CByte(i)).ToArray Public Event StatisticsUpdated As EventHandler Public ReadOnly Property Count As Integer Implements ICollection(Of IPAddress).Count Get Return statistics.Count End Get End Property Public Property DoNotFragment As Boolean = True Default Public ReadOnly Property Item(address As IPAddress) As MonitoredAddressStatistics Get If statistics.ContainsKey(address) Then Return statistics(address) Return Nothing End Get End Property Public ReadOnly Property IsReadOnly As Boolean Implements ICollection(Of IPAddress).IsReadOnly Get Return False End Get End Property Public ReadOnly Property IsRunning As Boolean Public Property MonitorRate As Integer = 1500 Public Property TimeOut As Integer = 5000 Public Property TimeToLive As Integer = 255 Protected runningTask As Task Protected statistics As New Dictionary(Of IPAddress, MonitoredAddressStatistics) Public Sub Add(item As IPAddress) Implements ICollection(Of IPAddress).Add statistics(item) = New MonitoredAddressStatistics(item) End Sub Public Function BeginMonitoring() As Task If runningTask IsNot Nothing Then Return runningTask _IsRunning = True runningTask = Task.Run(Async Function() Do While _IsRunning Await UpdateStatisticsAsync() OnStatisticsUpdated() Await Task.Delay(MonitorRate) Loop runningTask = Nothing End Function) Return runningTask End Function Public Sub Clear() Implements ICollection(Of IPAddress).Clear statistics.Clear() End Sub Public Function Contains(item As IPAddress) As Boolean Implements ICollection(Of IPAddress).Contains Return statistics.ContainsKey(item) End Function Public Sub CopyTo(array() As IPAddress, arrayIndex As Integer) Implements ICollection(Of IPAddress).CopyTo statistics.Keys.CopyTo(array, arrayIndex) End Sub Public Function GetEnumerator() As IEnumerator(Of IPAddress) Implements IEnumerable(Of IPAddress).GetEnumerator Return statistics.Keys.GetEnumerator End Function Private Function IEnumerable_GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator Return GetEnumerator() End Function Private Sub OnStatisticsUpdated() OnStatisticsUpdated(EventArgs.Empty) End Sub Protected Overridable Sub OnStatisticsUpdated(e As EventArgs) RaiseEvent StatisticsUpdated(Me, e) End Sub Public Function Remove(item As IPAddress) As Boolean Implements ICollection(Of IPAddress).Remove Return statistics.Remove(item) End Function Public Sub StopMonitoring() _IsRunning = False End Sub Public Async Function UpdateStatisticsAsync() As Task Dim options As New PingOptions(TimeToLive, DoNotFragment) Using pinger As New Ping For i = statistics.Count - 1 To 0 Step -1 Await statistics.Values.ElementAt(i).UpdateAsync(pinger, TimeOut, bufferData, options) Next End Using End Function End Class Public Class MonitoredAddressStatistics Public ReadOnly Property Address As IPAddress Public ReadOnly Property Available As Boolean Public ReadOnly Property AverageRoundTrip As Integer Public ReadOnly Property MaxRoundTrip As Integer Public ReadOnly Property MinRoundTrip As Integer Public ReadOnly Property SuccessRate As Double Protected pingCount As Integer Protected roundTripTotal As Long Protected successCount As Integer Public Sub New(ipAddress As IPAddress) Address = ipAddress MinRoundTrip = Integer.MaxValue End Sub Public Async Function UpdateAsync(pinger As Ping, timeOut As Integer, buffer() As Byte, options As PingOptions) As Task Dim result = Await pinger.SendPingAsync(Address, timeOut, buffer, options) pingCount += 1 _Available = (result.Status = IPStatus.Success) If Available Then successCount += 1 roundTripTotal += result.RoundtripTime If result.RoundtripTime < MinRoundTrip Then _MinRoundTrip = result.RoundtripTime If result.RoundtripTime > MaxRoundTrip Then _MaxRoundTrip = result.RoundtripTime _AverageRoundTrip = roundTripTotal \ pingCount End If
    _SuccessRate = successCount / pingCount End Function End Class



    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"


    Tuesday, March 28, 2017 5:25 PM
    Moderator
  • To be honest it didn't actually highlight any problem with the line you mentioned...

    I should have thought to explain that the option for Infer will change the behavior of Option Strict.

    I know that sounds odd but try it: Using your original code (not my altered one), at the top put this please:

    Option Strict On
    Option Explicit On
    Option Infer Off

    I think now you'll see some compile errors?

    *****

    The IP's (or URL's) - will just be a delimited text file then?


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Tuesday, March 28, 2017 5:25 PM
  • I knew Reed would know! ;-)

    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Tuesday, March 28, 2017 5:27 PM
  • To be honest it didn't actually highlight any problem with the line you mentioned...

    I should have thought to explain that the option for Infer will change the behavior of Option Strict.

    I know that sounds odd but try it: Using your original code (not my altered one), at the top put this please:

    Option Strict On
    Option Explicit On
    Option Infer Off

    I think now you'll see some compile errors?

    *****

    The IP's (or URL's) - will just be a delimited text file then?


    "A problem well stated is a problem half solved.” - Charles F. Kettering


    Ah yes I certainly see some errors now - nearly every line of code has something wrong with it!!

    Darren Rose

    Tuesday, March 28, 2017 5:28 PM
  • The IP's (or URL's) - will just be a delimited text file then?

    Yes that is correct

    Darren Rose

    Tuesday, March 28, 2017 5:29 PM
  • To be honest it didn't actually highlight any problem with the line you mentioned...

    I should have thought to explain that the option for Infer will change the behavior of Option Strict.

    I know that sounds odd but try it: Using your original code (not my altered one), at the top put this please:

    Option Strict On
    Option Explicit On
    Option Infer Off

    I think now you'll see some compile errors?

    *****

    The IP's (or URL's) - will just be a delimited text file then?


    "A problem well stated is a problem half solved.” - Charles F. Kettering


    Ah yes I certainly see some errors now - nearly every line of code has something wrong with it!!

    Darren Rose

    This isn't what I'll use, but this is my version of yours:

    Option Strict On Option Explicit On Option Infer Off Imports System.Net.NetworkInformation Public Class Form1 Private PingAddresses As New List(Of String) Private Sub Form1_Load(sender As System.Object, _ e As System.EventArgs) _ Handles MyBase.Load ' configure form ListView1.View = View.Details ListView1.FullRowSelect = True ListView1.GridLines = True ListView1.Columns.Add("Address", 150) ListView1.Columns.Add("Status", 100) ListView1.Columns.Add("Latency", 100) ' add to list of addresses to test PingAddresses.Add("www.bbc.co.uk") PingAddresses.Add("www.pcassistonline.co.uk") PingAddresses.Add("www.fgfgf.co.uk") Test() End Sub Private Sub Test() ' perform tests For Each Address As String In PingAddresses Dim PingResult As PingResults = GetPingResult(Address) Dim listViewInformation(2) As String listViewInformation(0) = PingResult.Address.ToString() listViewInformation(1) = PingResult.Status listViewInformation(2) = CStr(PingResult.Latency) Dim item As ListViewItem = New ListViewItem(listViewInformation) ListView1.Items.Add(item) If PingResult.Status <> "Success" Then item.ForeColor = Color.Red End If Next End Sub Public Class PingResults Public Address As String Public Status As String Public Latency As Long End Class Public Function GetPingResult(ByVal hostNameOrAddress As String) As PingResults Dim pr As PingResults = New PingResults() Const Data As String = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" Dim Buffer As Byte() = System.Text.Encoding.ASCII.GetBytes(Data) Const Timeout As Integer = 120 Dim Options As New PingOptions() With {.DontFragment = True} Dim Result As Net.NetworkInformation.PingReply Dim SendPing As New Net.NetworkInformation.Ping Try Result = SendPing.Send(hostNameOrAddress, Timeout, Buffer, Options) pr.Address = Result.Address.ToString pr.Status = Result.Status.ToString pr.Latency = Result.RoundtripTime Catch ex As Exception pr.Address = hostNameOrAddress pr.Status = "Failed" pr.Latency = 0 End Try Return pr End Function End Class



    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Tuesday, March 28, 2017 5:31 PM
  • Thanks Reed - that makes sense

    This tool will "mainly" be used in an internal network spread over various sites / IP subnets so DoS shouldn't pose an issue, but I take your point

    Will read through rest and look at your code shortly


    Darren Rose

    Tuesday, March 28, 2017 5:31 PM
  • The IP's (or URL's) - will just be a delimited text file then?

    Yes that is correct

    Darren Rose

    Ok, show me an example few lines of the text file to use and I should have enough to get started.

    (I'm still reading Reed's reply but I already know it's worth taking in).


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Tuesday, March 28, 2017 5:32 PM
  • The IP's (or URL's) - will just be a delimited text file then?

    Yes that is correct

    Darren Rose

    Ok, show me an example few lines of the text file to use and I should have enough to get started.

    (I'm still reading Reed's reply but I already know it's worth taking in).


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    192.168.10.2
    192.168.10.3
    192.168.2.4
    192.168.30.5
    192.168.0.1
    www.pcassistonline.co.uuk
    192.168.15.5
    192.168.10.0

    Yes definitely interesting read from Reed - now taking it in myself too

    Darren Rose

    Tuesday, March 28, 2017 5:36 PM

  • 192.168.10.2
    192.168.10.3
    192.168.2.4
    192.168.30.5
    192.168.0.1
    www.pcassistonline.co.uuk
    192.168.15.5
    192.168.10.0

    Yes definitely interesting read from Reed - now taking it in myself too

    Darren Rose

    I thought you were going to have a number of repeats (per entry) also?

    *****

    Give Reed's version a go - he's likely already got what you want there. :)


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Tuesday, March 28, 2017 5:42 PM
  • Thanks Reed - that makes sense

    This tool will "mainly" be used in an internal network spread over various sites / IP subnets so DoS shouldn't pose an issue, but I take your point

    Will read through rest and look at your code shortly


    Darren Rose

    Even if trigger a false DoS attack isn't a concern, do keep overall network traffic in mind.  It won't do to create a tool for troubleshooting network issues if the tool itself creates a network issue.  :P

    Let me know if you have any questions over the code.


    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"

    Tuesday, March 28, 2017 5:44 PM
    Moderator
  • Reed,

    What do you suppose the "hit frequency" guidelines should be?


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Tuesday, March 28, 2017 5:46 PM
  • I knew Reed would know! ;-)

    "A problem well stated is a problem half solved.” - Charles F. Kettering

    =)

    I have some idea anyway.  I'm pretty sure that the network statistics stuff you guys were also talking about will only apply to the local machine and not a remote host.  I believe you'd have to be running software on all hosts to transmit local IP statistics to a centralized point if you wanted to measure more in-depth network statistics.  At that point you might as well install a network management suite because you'd be getting into some tricky programming.  If everything isn't done just right, you risk creating network congestion with your monitoring solution.  I have no love for SpiceWorks but lots of people use it and it does mostly do the job - I am just very leery of the advertising and data sharing.


    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"

    Tuesday, March 28, 2017 5:48 PM
    Moderator
  • I thought you were going to have a number of repeats (per entry) also?

    Yes sorry, if so then would do comma separated perhaps e.g. 192.168.10.2,10,192.168.10.3,10,192,168,2.4,20 etc

    Whatever is easiest for you to read in to the program - happy to do it however you recommend


    Darren Rose

    Tuesday, March 28, 2017 6:09 PM
  • Even if trigger a false DoS attack isn't a concern, do keep overall network traffic in mind.  It won't do to create a tool for troubleshooting network issues if the tool itself creates a network issue.  :P

    Let me know if you have any questions over the code.

    Fair point

    Thanks, will do


    Darren Rose

    Tuesday, March 28, 2017 6:09 PM
  • I knew Reed would know! ;-)


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    =)

    I have some idea anyway.  I'm pretty sure that the network statistics stuff you guys were also talking about will only apply to the local machine and not a remote host.  I believe you'd have to be running software on all hosts to transmit local IP statistics to a centralized point if you wanted to measure more in-depth network statistics.  At that point you might as well install a network management suite because you'd be getting into some tricky programming.  If everything isn't done just right, you risk creating network congestion with your monitoring solution.  I have no love for SpiceWorks but lots of people use it and it does mostly do the job - I am just very leery of the advertising and data sharing.


    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"

    Yes I also believe the network stats I mentioned would be local machine rather than remote and I have done a lot of that getting all the stats and information I can pull from networkinformation class to show packet errors and such like - this may well prove enough or to be useful

    Would rather have my own (even if basic) solution to do some testing, not really a fan of things like SpiceWorks, I know it is quite popular but it does so much else that isn't needed and so far have implemented most other things myself without needing 3rd party tools.

    I know networking is different and yes need to be careful not to make more congestion using a tool, but just something to run on demand to test various links to servers / remote sites to try and pin point issues they are having where network slows down for no obvious reason


    Darren Rose

    Tuesday, March 28, 2017 6:12 PM
  • Yes sorry, if so then would do comma separated perhaps e.g. 192.168.10.2,10,192.168.10.3,10,192,168,2.4,20 etc

    Whatever is easiest for you to read in to the program - happy to do it however you recommend


    Darren Rose

    I would think it would "per line", the IP/Host, the number of times to hit, the hit frequency ... maybe other things?

    Like I said to start with, this isn't my forte. I know that Reed knows it backward and forward and obviously you do too, but I don't. ;-)


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Tuesday, March 28, 2017 6:16 PM
  • I would think it would "per line", the IP/Host, the number of times to hit, the hit frequency ... maybe other things?

    Like I said to start with, this isn't my forte. I know that Reed knows it backward and forward and obviously you do too, but I don't. ;-)


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Yes that makes sense

    I have just been playing with Reed's code and yes it does get me some results, just need to use that same sort of idea to read from text file, and output to a listview (or similar), so I can easily show perhaps using colour if destination up or down and average over time for latency (roundtrip)


    Darren Rose

    Tuesday, March 28, 2017 6:36 PM
  • Reed,

    What do you suppose the "hit frequency" guidelines should be?


    "A problem well stated is a problem half solved.” - Charles F. Kettering


    I'd say no faster than every 500ms, and over a full second is probably best. But that's just my estimation. It may be that a single host is unlikely to trip an alarm, but since we're eating someone else's bandwidth, and resolution of more than a second is likely not useful, I think a second-and-a-half or so would be considered playing nice.

    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"

    Tuesday, March 28, 2017 6:37 PM
    Moderator
  • I would think it would "per line", the IP/Host, the number of times to hit, the hit frequency ... maybe other things?

    Like I said to start with, this isn't my forte. I know that Reed knows it backward and forward and obviously you do too, but I don't. ;-)


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Yes that makes sense

    I have just been playing with Reed's code and yes it does get me some results, just need to use that same sort of idea to read from text file, and output to a listview (or similar), so I can easily show perhaps using colour if destination up or down and average over time for latency (roundtrip)


    Darren Rose

    Well, if you're back to the UI end of things, try using what he has and then put it all together.

    Later if you want to do it differently then I'll do what I can to help. :)


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Tuesday, March 28, 2017 6:38 PM
  • ...

    Would rather have my own (even if basic) solution to do some testing, not really a fan of things like SpiceWorks, I know it is quite popular but it does so much else that isn't needed and so far have implemented most other things myself without needing 3rd party tools.

    I know networking is different and yes need to be careful not to make more congestion using a tool, but just something to run on demand to test various links to servers / remote sites to try and pin point issues they are having where network slows down for no obvious reason


    Darren Rose

    OK, so long as you understand its only worth building a rudimentary toolset this way.  This would be a perfectly acceptable solution for basic connectivity and response checks or to watch or intermittent failures.


    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"

    Tuesday, March 28, 2017 6:39 PM
    Moderator


  • I'd say no faster than every 500ms, and over a full second is probably best. But that's just my estimation. It may be that a single host is unlikely to trip an alarm, but since we're eating someone else's bandwidth, and resolution of more than a second is likely not useful, I think a second-and-a-half or so would be considered playing nice.

    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"

    That sounds reasonable.

    If this develops, then I'll put something together to take that into account. With a list of IP's to test, it might be there's little difference in overall time.


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Tuesday, March 28, 2017 6:58 PM
  • This isn't what I'll use, but this is my version of yours:

    code removed

    Thanks - that was handy to see the differences between my original code - all errors make sense now as to why they needed doing differently

    Darren Rose

    Tuesday, March 28, 2017 7:13 PM
  • I would think it would "per line", the IP/Host, the number of times to hit, the hit frequency ... maybe other things?

    Like I said to start with, this isn't my forte. I know that Reed knows it backward and forward and obviously you do too, but I don't. ;-)


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Yes that makes sense

    I have just been playing with Reed's code and yes it does get me some results, just need to use that same sort of idea to read from text file, and output to a listview (or similar), so I can easily show perhaps using colour if destination up or down and average over time for latency (roundtrip)


    Darren Rose

    Well, if you're back to the UI end of things, try using what he has and then put it all together.

    Later if you want to do it differently then I'll do what I can to help. :)


    "A problem well stated is a problem half solved.” - Charles F. Kettering


    Yes UI but also need to do changes in frequency for different IP addresses and other bits, so perhaps better to do from scratch than trying to amend other code?

    Darren Rose

    Tuesday, March 28, 2017 7:14 PM


  • Yes UI but also need to do changes in frequency for different IP addresses and other bits, so perhaps better to do from scratch than trying to amend other code?

    Darren Rose

    I'll try to get started tomorrow if I can then.

    I'm waiting on an e-mail so that I can continue what I'm on (a work-related project), so hopefully that will be finished by tomorrow.


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Tuesday, March 28, 2017 7:21 PM


  • Yes UI but also need to do changes in frequency for different IP addresses and other bits, so perhaps better to do from scratch than trying to amend other code?

    Darren Rose

    I'll try to get started tomorrow if I can then.

    I'm waiting on an e-mail so that I can continue what I'm on (a work-related project), so hopefully that will be finished by tomorrow.


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Thanks Frank - no hurry

    I will also then at least learn about creating a class properly how you do it as we go along

    We could perhaps use a Dev control to show results if better/easier?


    Darren Rose

    Tuesday, March 28, 2017 7:25 PM


  • Thanks Frank - no hurry

    I will also then at least learn about creating a class properly how you do it as we go along

    We could perhaps use a Dev control to show results if better/easier?


    Darren Rose

    What do you want to call this?

    What I have in mind won't have any controls.


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Tuesday, March 28, 2017 7:36 PM
  • What do you want to call this?

    What I have in mind won't have any controls.


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    PingTool or PingClass ?

    That's fine


    Darren Rose

    Tuesday, March 28, 2017 7:43 PM
  • Darren,

    Ok, I'll see what I come up with then.


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Tuesday, March 28, 2017 8:34 PM
  • Here's a refactoring to use a ListView, move the ping options onto each address item, and parse a text file with the addresses and options.

    Imports System.Net
    Imports System.Net.NetworkInformation
    
    Public Class Form1
        Friend WithEvents StartButton As New Button With {.AutoSize = True, .Dock = DockStyle.Top, .Text = "Start Monitor"}
        Friend WithEvents StopButton As New Button With {.AutoSize = True, .Dock = DockStyle.Top, .Text = "Stop Monitor"}
        Friend WithEvents ListView1 As New ListView With {.Dock = DockStyle.Fill}
    
        Private addressItems As New Dictionary(Of IPAddress, ListViewItem)
        Private WithEvents monitor As New IpAddressMonitor
    
        Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
            monitor.StopMonitoring()
        End Sub
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Controls.Add(ListView1)
            Controls.Add(StopButton)
            Controls.Add(StartButton)
    
            With ListView1.Columns
                .Add("Address")
                .Add("Available")
                .Add("Success %")
                .Add("Min Time")
                .Add("Max Time")
                .Add("Avg Time")
            End With
    
            ListView1.View = View.Details
    
            Using tfp As New FileIO.TextFieldParser("AddressInfo.txt")
                tfp.SetDelimiters(",")
                While Not tfp.EndOfData
                    Dim fields = tfp.ReadFields()
                    If fields.Length = 5 Then
                        Dim address As IPAddress = Nothing
                        If Not IPAddress.TryParse(fields(0), address) Then
                            Try
                                Dim dnsResults = Dns.GetHostAddresses(fields(0))
                                address = (From r In dnsResults Where r.AddressFamily = Sockets.AddressFamily.InterNetwork).FirstOrDefault
                            Catch ex As Exception
                                Continue While
                            End Try
                        End If
                        If address IsNot Nothing Then
                            monitor.Add(address)
                            With monitor(address)
                                .MonitorRate = CInt(fields(1))
                                .TimeOut = CInt(fields(2))
                                .TimeToLive = CInt(fields(3))
                                .DoNotFragment = CBool(fields(4))
                            End With
                            Dim listItem As New ListViewItem
                            listItem.UseItemStyleForSubItems = False
                            listItem.Text = address.ToString
                            For i = 0 To 4
                                listItem.SubItems.Add(String.Empty)
                            Next
    
                            addressItems(address) = ListView1.Items.Add(listItem)
                        End If
                    End If
                End While
            End Using
        End Sub
    
        Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles StartButton.Click
            Try
                StartButton.Enabled = False
                Await monitor.BeginMonitoring
            Catch ex As Exception
                Stop
            Finally
                StartButton.Enabled = True
            End Try
        End Sub
    
        Private Sub Button2_Click(sender As Object, e As EventArgs) Handles StopButton.Click
            monitor.StopMonitoring()
        End Sub
    
        Private Sub monitor_StatisticsUpdated(sender As Object, e As StatisticUpdatedEventArgs) Handles monitor.StatisticsUpdated
            If InvokeRequired Then
                Invoke(Sub()
                           monitor_StatisticsUpdated(sender, e)
                       End Sub)
            Else
                Dim listItem As ListViewItem = addressItems(e.Statistic.Address)
                With listItem.SubItems.Item(1)
                    .Text = e.Statistic.Available.ToString
                    If e.Statistic.Available Then
                        .BackColor = Color.DarkGreen
                        .ForeColor = Color.White
                    Else
                        .BackColor = Color.DarkRed
                        .ForeColor = Color.Gray
                    End If
                End With
                listItem.SubItems.Item(2).Text = e.Statistic.SuccessRate.ToString("p0")
                listItem.SubItems.Item(3).Text = e.Statistic.MinRoundTrip
                listItem.SubItems.Item(4).Text = e.Statistic.MaxRoundTrip
                listItem.SubItems.Item(5).Text = e.Statistic.AverageRoundTrip
            End If
        End Sub
    End Class
    
    Public Class IpAddressMonitor
        Implements ICollection(Of IPAddress)
    
        Protected Shared bufferData() As Byte = (From i In Enumerable.Range(0, 32) Select CByte(i)).ToArray
    
        Public Event StatisticsUpdated As EventHandler(Of StatisticUpdatedEventArgs)
    
        Public ReadOnly Property Count As Integer Implements ICollection(Of IPAddress).Count
            Get
                Return statistics.Count
            End Get
        End Property
    
        Default Public ReadOnly Property Item(address As IPAddress) As MonitoredAddressStatistics
            Get
                If statistics.ContainsKey(address) Then Return statistics(address)
                Return Nothing
            End Get
        End Property
    
        Public ReadOnly Property IsReadOnly As Boolean Implements ICollection(Of IPAddress).IsReadOnly
            Get
                Return False
            End Get
        End Property
    
        Public ReadOnly Property IsRunning As Boolean
    
        Public Property MaximumResolution As Integer = 50
    
        Protected runningTask As Task
        Protected statistics As New Dictionary(Of IPAddress, MonitoredAddressStatistics)
    
        Public Sub Add(item As IPAddress) Implements ICollection(Of IPAddress).Add
            statistics(item) = New MonitoredAddressStatistics(item)
        End Sub
    
        Public Function BeginMonitoring() As Task
            If runningTask IsNot Nothing Then Return runningTask
            _IsRunning = True
            runningTask = Task.Run(Async Function()
                                       Do While _IsRunning
                                           Await UpdateStatisticsAsync()
                                           Await Task.Delay(MaximumResolution)
                                       Loop
                                       runningTask = Nothing
                                   End Function)
            Return runningTask
        End Function
    
        Public Sub Clear() Implements ICollection(Of IPAddress).Clear
            statistics.Clear()
        End Sub
    
        Public Function Contains(item As IPAddress) As Boolean Implements ICollection(Of IPAddress).Contains
            Return statistics.ContainsKey(item)
        End Function
    
        Public Sub CopyTo(array() As IPAddress, arrayIndex As Integer) Implements ICollection(Of IPAddress).CopyTo
            statistics.Keys.CopyTo(array, arrayIndex)
        End Sub
    
        Public Function GetEnumerator() As IEnumerator(Of IPAddress) Implements IEnumerable(Of IPAddress).GetEnumerator
            Return statistics.Keys.GetEnumerator
        End Function
    
        Private Function IEnumerable_GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
            Return GetEnumerator()
        End Function
    
        Private Sub OnStatisticsUpdated(statistic As MonitoredAddressStatistics)
            OnStatisticsUpdated(New StatisticUpdatedEventArgs(statistic))
        End Sub
    
        Protected Overridable Sub OnStatisticsUpdated(e As StatisticUpdatedEventArgs)
            RaiseEvent StatisticsUpdated(Me, e)
        End Sub
    
        Public Function Remove(item As IPAddress) As Boolean Implements ICollection(Of IPAddress).Remove
            Return statistics.Remove(item)
        End Function
    
        Public Sub StopMonitoring()
            _IsRunning = False
        End Sub
    
        Public Async Function UpdateStatisticsAsync() As Task
            Using pinger As New Ping
                For i = statistics.Count - 1 To 0 Step -1
                    Dim monitoredAddress = statistics.Values.ElementAt(i)
                    Dim result = Await monitoredAddress.UpdateAsync(pinger, bufferData)
                    If result Then OnStatisticsUpdated(monitoredAddress)
                Next
            End Using
        End Function
    End Class
    
    Public Class MonitoredAddressStatistics
        Public ReadOnly Property Address As IPAddress
        Public ReadOnly Property Available As Boolean
        Public ReadOnly Property AverageRoundTrip As Integer
        Public Property DoNotFragment As Boolean
        Public ReadOnly Property MaxRoundTrip As Integer
        Public ReadOnly Property MinRoundTrip As Integer
        Public Property MonitorRate As Integer
        Public ReadOnly Property SuccessRate As Double
        Public Property TimeOut As Integer
        Public Property TimeToLive As Integer
    
        Protected pingCount As Integer
        Protected roundTripTotal As Long
        Protected successCount As Integer
        Protected lastUpdate As Date
    
        Public Sub New(ipAddress As IPAddress)
            Address = ipAddress
            MinRoundTrip = Integer.MaxValue
        End Sub
    
        Public Async Function UpdateAsync(pinger As Ping, buffer() As Byte) As Task(Of Boolean)
            If Now.Subtract(lastUpdate).TotalMilliseconds >= MonitorRate Then
                Dim options As New PingOptions(TimeToLive, DoNotFragment)
                Dim result = Await pinger.SendPingAsync(Address, TimeOut, buffer, options)
                pingCount += 1
                _Available = (result.Status = IPStatus.Success)
                If Available Then
                    successCount += 1
                    roundTripTotal += result.RoundtripTime
                    If result.RoundtripTime < MinRoundTrip Then _MinRoundTrip = result.RoundtripTime
                    If result.RoundtripTime > MaxRoundTrip Then _MaxRoundTrip = result.RoundtripTime
                    _AverageRoundTrip = roundTripTotal \ pingCount
                End If
                _SuccessRate = successCount / pingCount
                lastUpdate = Now
                Return True
            End If
            Return False
        End Function
    End Class
    
    Public Class StatisticUpdatedEventArgs
        Inherits EventArgs
        Public ReadOnly Property Statistic As MonitoredAddressStatistics
        Protected Friend Sub New(addressStatistic As MonitoredAddressStatistics)
            Statistic = addressStatistic
        End Sub
    End Class

    The text file contains the IP address, ping interval, time out, time to live, and fragmentation option.  Here's an example:

    192.168.10.2, 150, 200, 255, True
    192.168.10.3, 150, 200, 255, True
    192.168.2.4, 150, 200, 255, True
    192.168.30.5, 150, 200, 255, True
    192.168.0.1, 150, 200, 255, True
    www.pcassistonline.co.uk, 150, 200, 255, True
    192.168.15.5, 150, 200, 255, True
    192.168.10.0, 150, 200, 255, True
    8.8.8.8, 150, 200, 255, True
    www.bing.com, 150, 200, 255, True


    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"

    Tuesday, March 28, 2017 9:07 PM
    Moderator
  • Thank you Reed - that is very kind

    Couple of queries:-

    1) If a host is down then Min time shows as 2147483647 as per screenshot

    2) Is it possible for the website entries rather than internal IP's to show the name as well as IP e.g. for www.bing.com show IP and name such as 204.79.197.200 (www.bing.com) or perhaps have a separate column? as for the internal IPs they will have host names that can be shown such as MailServer1 , DC1 etc - just makes it easier to identify the server/hosts when glancing at list


    Darren Rose

    Tuesday, March 28, 2017 9:16 PM
  • Thanks Frank - no hurry

    I just got yet another project (yes, of course at 4:30 in the afternoon...).

    It looks to be fairly simple, but I have to address "real work" first, so I may be an extra day or two getting back to you on this.


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Tuesday, March 28, 2017 9:31 PM


  • Darren Rose

    Reed can very well answer for himself, but let me add this:

    In my opinion, each line that you see there should represent an instance of a class and all of the properties/fields which are intrinsically value types should be nullable types with a complimentary string property.

    If the column needs to be sortable though - as with a DataGridView - that blows that idea. ;-)

    Instead, use a value like -1 (and keep it as a value type, no change).

    Food for thought and I'll be back on it Thursday if you still want me to.


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Tuesday, March 28, 2017 10:09 PM
  • The example sets the min time to Int.Max until the first ping.  You could swap that out for Integer? and test for the null to display some other value (or just test for Int.Max and display some other value).

    You could use DNS to get the host name associated with each IP address, if any, and include that in the data you display.  I would probably just edit the text file parsing routine to do a host name look up on each IP address.


    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"

    Tuesday, March 28, 2017 10:11 PM
    Moderator
  • Reed can very well answer for himself, but let me add this:

    In my opinion, each line that you see there should represent an instance of a class and all of the properties/fields which are intrinsically value types should be nullable types with a complimentary string property.

    If the column needs to be sortable though - as with a DataGridView - that blows that idea. ;-)

    Instead, use a value like -1 (and keep it as a value type, no change).

    Food for thought and I'll be back on it Thursday if you still want me to.


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Thanks for reply Frank

    Yes fair point

    It would be handy to be able to sort the columns then I can easily see which endpoints have the highest average response time etc - which would be good if I had 20/30+ servers in the list

    -1 or 0 would be fine for those with no other value to show though


    Darren Rose

    Tuesday, March 28, 2017 10:24 PM
  • Darren,

    I'll get to it, I just can't do that soon.

    Please don't discount Reed's work though - he's the "real deal" pro, not me. :)


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Tuesday, March 28, 2017 10:28 PM
  • Darren,

    I'll get to it, I just can't do that soon.

    Please don't discount Reed's work though - he's the "real deal" pro, not me. :)


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    That's fine - I understand

    No definitely not discounting Reed's work - I appreciate it - if nothing else it is giving me ideas as to what is needed and what isn't needed etc, so has been very useful


    Darren Rose

    Tuesday, March 28, 2017 10:30 PM
  • Darren,

    I'm trying to get my feet wet with this and I had a thought:

    Whenever you give it an IP (or a string that can be resolved to an IP), if you run it using your example from yesterday, you'll get this:

    In that one I used "192.168.10.2" that you listed yesterday. You can see above that it timed out. I set the time out to 5000 just to be sure, but it doesn't matter. It took five seconds and then returned what you see above.

    As a test, I next tried this:

    Dim hostname As IPHostEntry = Dns.GetHostEntry("192.168.10.2")


    It pretty quickly threw a socket exception:

    Just to be sure, I ran both tests using www.google.com:

    Here's my point:

    If we can find out in advance that an IP is unreachable, then why not eliminate it from the test - especially a test that runs multiple times.

    Your thoughts?


    "A problem well stated is a problem half solved.” - Charles F. Kettering



    • Edited by Frank L. Smith Wednesday, March 29, 2017 2:49 PM ...I can't type today
    Wednesday, March 29, 2017 2:43 PM
  • Two ways of thinking about this in my opinion

    If I was just running the tool to say loop ten times to get average of roundtriptime - then yes if a host is unreachable then agreed we may as well eliminate it from that test

    But if say I decided to leave tool running in background for hours/days to be a constant log/alert of server status then we would need it to keep trying an unreachable address at some point - as it may be unreachable at 12.30pm but could come back online at 12.40pm for example

    Hope that makes sense


    Darren Rose

    Wednesday, March 29, 2017 2:56 PM
  • Two ways of thinking about this in my opinion

    If I was just running the tool to say loop ten times to get average of roundtriptime - then yes if a host is unreachable then agreed we may as well eliminate it from that test

    But if say I decided to leave tool running in background for hours/days to be a constant log/alert of server status then we would need it to keep trying an unreachable address at some point - as it may be unreachable at 12.30pm but could come back online at 12.40pm for example

    Hope that makes sense


    Darren Rose


    Yes, but I didn't know you meant that you were going to run it "constantly". If that's the case then what's the point of having a count at all? Count = infinity?

    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Wednesday, March 29, 2017 2:59 PM
  • Two ways of thinking about this in my opinion

    If I was just running the tool to say loop ten times to get average of roundtriptime - then yes if a host is unreachable then agreed we may as well eliminate it from that test

    But if say I decided to leave tool running in background for hours/days to be a constant log/alert of server status then we would need it to keep trying an unreachable address at some point - as it may be unreachable at 12.30pm but could come back online at 12.40pm for example

    Hope that makes sense


    Darren Rose


    Yes, but I didn't know you meant that you were going to run it "constantly". If that's the case then what's the point of having a count at all? Count = infinity?

    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Just thinking on my feet really - like all useful code created by you I like to use it as much as possible!! and yes the main use is to run it when we have problems to see if any particular servers/end points are not responding or slow - hence running for x number of loops

    But I thought it may also be useful sometimes to use same class/code in a monitoring tool to alert when slow or offline - so yes could be an option to do it x times or to do it continually, only difference would be that if doing it x times we would do it every few seconds (as per Reeds comment about not doing it too often due to DoS etc), if running constantly then we could do it every 30 minutes or something

    If delay and how often to run it are options we can set then it opens up class to being used for other purposes which is always good


    Darren Rose

    Wednesday, March 29, 2017 3:06 PM

  • Just thinking on my feet really - like all useful code created by you I like to use it as much as possible!! and yes the main use is to run it when we have problems to see if any particular servers/end points are not responding or slow - hence running for x number of loops

    But I thought it may also be useful sometimes to use same class/code in a monitoring tool to alert when slow or offline - so yes could be an option to do it x times or to do it continually, only difference would be that if doing it x times we would do it every few seconds (as per Reeds comment about not doing it too often due to DoS etc), if running constantly then we could do it every 30 minutes or something

    If delay and how often to run it are options we can set then it opens up class to being used for other purposes which is always good


    Darren Rose

    Just thinking here: There's a distinct difference though.

    If it runs a test x times, "round robin" style and checking that it doesn't hit that server any faster than whatever the specification is, then the test is concluded and you get the results - at the end of the test.

    If you want it to be "loop forever", somewhere or other it needs to give you intermediate results. Is that what you have in mind?


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Wednesday, March 29, 2017 3:15 PM
  • I was assuming when I use your class then I will be able to show my results live on a form in a list or grid or whatever so for each server/endpoint it would show me

    name, IP address, status (up/down), average roundtrip, max roundtrip, min roundtrip

    So when finished looping say 10 times the form would show me last test results

    If running / looping forever then I can look at form to see current results

    Sorry if I am missing something here - been doing tax paperwork and it is a nightmare as usual!


    Darren Rose

    Wednesday, March 29, 2017 3:29 PM
  • I was assuming when I use your class then I will be able to show my results live on a form in a list or grid or whatever so for each server/endpoint it would show me

    name, IP address, status (up/down), average roundtrip, max roundtrip, min roundtrip

    So when finished looping say 10 times the form would show me last test results

    If running / looping forever then I can look at form to see current results

    Sorry if I am missing something here - been doing tax paperwork and it is a nightmare as usual!


    Darren Rose

    I [thought] you wanted it to loop and give you results at the end, but I can raise an event - just thinking out loud about it running through the list - hmm, I don't know. I'll get there and see where it goes.

    How many might be in the list of IP's do you think?

    I'll definitely change the "TestResults" class - one more mode at least: "NotYetTested". 

    Is that reasonable?


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Wednesday, March 29, 2017 3:38 PM
  • No I would like to be able to see results live so to speak, so as it runs it updates the form using whatever control works best - could then have a button to save report to file or something

    So perhaps two modes - "continuous" so form just constantly updates or "test mode" where it just loops x times and then form shows results? whatever is the easiest way for you to do in class really

    I would anticipate no more than 50 but probably in normal use about 35


    Darren Rose

    Wednesday, March 29, 2017 3:45 PM
  • No I would like to be able to see results live so to speak, so as it runs it updates the form using whatever control works best - could then have a button to save report to file or something

    So perhaps two modes - "continuous" so form just constantly updates or "test mode" where it just loops x times and then form shows results? whatever is the easiest way for you to do in class really

    I would anticipate no more than 50 but probably in normal use about 35


    Darren Rose

    My head is full of things from 'real work' projects, but I think that once I get into it then maybe it'll all come together.

    *****

    From earlier, you want it to run out on time rather than any sort of pre-test then, right?


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Wednesday, March 29, 2017 4:00 PM
  • That's fine - same here - I hate tax returns! :(

    ****

    Sorry don't get what you are asking?


    Darren Rose

    Wednesday, March 29, 2017 4:11 PM
  • Darren,

    I read in this thread that it is about an LAN. While most replies are in the way I read it about Internet. 

    Allmost all LAN's are currently Ethernet. But there are some which are not, therefore your first problem is to find what kind of fysical layer is used. 

    https://en.wikipedia.org/wiki/IEEE_802

    However, the most chance is Ethernet if it is a Lan. 802.3 and then it is based on Collision (two stations send at exact the same time) detect and avoid (a signal is send a with a little bit longer or shorter interval if a collision is detected). 

    By sending than with VB more data over the line to test the line, you are in fact creating more collisions, therefore is VB not the right tool to use for that. 

    In this thread Reed wrote already about special tools, (but those are connected to the routers or switches) and done by LAN administrators. 

    But that is then for the kind of Network which is used. 

    You can of course always use one ping detect if the server (or whatever) is up, that takes so few time that it harms nothing. However, be than aware that IP addresses are seldom fixed. In a well organized Lan are currently leased IP addresses used which are given by the DHCP server.


    Success
    Cor

    Wednesday, March 29, 2017 4:15 PM
  • Darren,

    I read in this thread that it is about an LAN. While most replies are in the way I read it about Internet. 

    Allmost all LAN's are currently Ethernet. But there are some which are not, therefore your first problem is to find what kind of fysical layer is used. 

    https://en.wikipedia.org/wiki/IEEE_802

    However, the most chance is Ethernet if it is a Lan. 802.3 and then it is based on Collision (two stations send at exact the same time) detect and avoid (a signal is send a with a little bit longer or shorter interval if a collision is detected). 

    By sending than with VB more data over the line to test the line, you are in fact creating more collisions, therefore is VB not the right tool to use for that. 

    In this thread Reed wrote already about special tools, (but those are connected to the routers or switches) and done by LAN administrators. 

    But that is then for the kind of Network which is used. 

    You can of course always use one ping detect if the server (or whatever) is up, that takes so few time that it harms nothing. However, be than aware that IP addresses are seldom fixed. In a well organized Lan are currently leased IP addresses used which are given by the DHCP server.


    Success
    Cor

    Hi Cor

    Thanks for your reply

    This thread and my requirement is mainly talking about LAN not Internet

    It is Ethernet based so already know the physical layer

    IP addresses for all devices such as servers, switches, routers etc are in this case (and most cases I have ever seen) fixed IP - the client/users computers (desktop, laptops, tablets) are DHCP - but we are not interested in those - just the servers, switches, gateway, links etc

    I realise how it all works as I am the network engineer for the company and put the network together, so fully understand packets, collisions, infrastructure etc

    This tool is mainly to make sure everything is up, and by use of roundtriptime/latency seeing if any areas slower to respond to help work out areas causing bottlenecks etc - currently this is done manually using command prompt and ping and helps, so a tool to do it is just automating the process


    Darren Rose

    Wednesday, March 29, 2017 4:21 PM

  • Sorry don't get what you are asking?


    Darren Rose

    I meant what started this from today when I asked about using Dns.GetHostEntry to test whether or not an entry should be pre-tested.

    Before answering that though, you said you wanted this:

    name, IP address, status (up/down), average roundtrip, max roundtrip, min roundtrip

    The "name" - that's the host name you mean? Keep in mind that I know I'm out of my bailiwick here, but I assume that's what you mean?

    If so, then I don't have any choice but to use Dns.GetHostEntry -- or am I missing it all?


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Wednesday, March 29, 2017 4:28 PM
  • From the discussion about having it perhaps running in background every 30 / 60 minutes or something then we would not know if server up/down unless we pinged it, so for that perhaps doing a pre-test wouldn't work, as when would you pre-test when you first ran app or every now and again to make sure a down server is not now up?

    So perhaps it will be easier not to use Dns.GetHostEntry and just go on if ping failed then it means it is down

    For name I don't actually mind, it was more thinking a list of IP addresses is not always obvious at a glance as to which refers to what item - so either use DNS.GetHostEntry and then can show HostName and IP Address or to make it simper in the list of servers text file we could just have a name for each IP just for identification purposes e.g. not obtained using GetHostEntry just read from file, so just a "friendly name" or something e.g

    "Mail Server", 192.168.10.2

    "Switch in downstairs office", 192.168.20.3


    Darren Rose

    Wednesday, March 29, 2017 4:34 PM
  • From the discussion about having it perhaps running in background every 30 / 60 minutes or something then we would not know if server up/down unless we pinged it, so for that perhaps doing a pre-test wouldn't work, as when would you pre-test when you first ran app or every now and again to make sure a down server is not now up?

    So perhaps it will be easier not to use Dns.GetHostEntry and just go on if ping failed then it means it is down

    For name I don't actually mind, it was more thinking a list of IP addresses is not always obvious at a glance as to which refers to what item - so either use DNS.GetHostEntry and then can show HostName and IP Address or to make it simper in the list of servers text file we could just have a name for each IP just for identification purposes e.g. not obtained using GetHostEntry just read from file, so just a "friendly name" or something e.g

    "Mail Server", 192.168.10.2

    "Switch in downstairs office", 192.168.20.3


    Darren Rose

    I see - I think.

    So then in a "configuration" for it, you want to give it an "alias name" along with the IP? That makes sense if that's what you mean, but with 50 of them, maybe that's not what you mean?


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Wednesday, March 29, 2017 4:39 PM
  • "alias" that was the word I was looking for and meant!!

    I think that would work if we can't show its real name / host name by using DNS.GetHostEntry


    Darren Rose

    Wednesday, March 29, 2017 4:41 PM
  • "alias" that was the word I was looking for and meant!!

    I think that would work if we can't show its real name / host name by using DNS.GetHostEntry


    Darren Rose

    Well, here's how it could work then.

    Like the last gig we did, there will be a class that's essentially all of the settings per IP (like loop count, if applicable, timeout, etc). Then a process class will use an IEnumerable(Of...) of those instances.

    Per instance: Optionally, you give each an alias name. If you don't choose to set it, then it will use the Host name AFTER it's been proven that it returned something (otherwise it might throw a socket exception).

    Maybe that?


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Wednesday, March 29, 2017 4:52 PM
  • Yes that make sense - so if it can determine host name it shows it - if it can't then it shows "alias" - then whatever happens I will always know the name one way or another

    Darren Rose

    Wednesday, March 29, 2017 4:55 PM
  • Yes that make sense - so if it can determine host name it shows it - if it can't then it shows "alias" - then whatever happens I will always know the name one way or another

    Darren Rose


    Is that your preferred order of priority then? I would think you'd want it to be the alias name (if it exists), no?

    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Wednesday, March 29, 2017 4:57 PM
  • preferred order would be its real/proper name e.g. hostname if it can get it, or if it can't because it is down or not contactable then it shows the alias name instead

    Darren Rose

    Wednesday, March 29, 2017 5:00 PM
  • P.S. Obviously we are basing this on me using IP addresses in the text file - but what if (or) could I sometimes use the hostname instead e.g. MailServer1 rather than 192.168.10.5

    Would this be possible - or would it complicate things? not a problem if can't be done that way, just assume as for website we would use name www.google.co.uk rather than IP anyway


    Darren Rose

    Wednesday, March 29, 2017 5:02 PM
  • preferred order would be its real/proper name e.g. hostname if it can get it, or if it can't because it is down or not contactable then it shows the alias name instead

    Darren Rose

    Ok,

    Try this just for the sake of knowing:

    Dim entry As IPHostEntry = Dns.GetHostEntry("192.168.10.2")

    Change the IP to one that's live and check the .HostName property.

    I did that here and the value was ... meaningless to me.

    I'm curious what yours will show (or rather, if it's meaningful to you).


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Wednesday, March 29, 2017 5:05 PM
  • P.S. Obviously we are basing this on me using IP addresses in the text file - but what if (or) could I sometimes use the hostname instead e.g. MailServer1 rather than 192.168.10.5

    Would this be possible - or would it complicate things? not a problem if can't be done that way, just assume as for website we would use name www.google.co.uk rather than IP anyway


    Darren Rose

    The URL will work, sure. I don't know about the other way around.


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Wednesday, March 29, 2017 5:07 PM
  • preferred order would be its real/proper name e.g. hostname if it can get it, or if it can't because it is down or not contactable then it shows the alias name instead


    Darren Rose

    Ok,

    Try this just for the sake of knowing:

    Dim entry As IPHostEntry = Dns.GetHostEntry("192.168.10.2")

    Change the IP to one that's live and check the .HostName property.

    I did that here and the value was ... meaningless to me.

    I'm curious what yours will show (or rather, if it's meaningful to you).


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Just did it for a variety of IP addresses at home (rather than on work network) and the .HostName returned the full name of computer as I would expect

    So for my main computer which is 192.168.1.109 it returned XPSDESKTOP

    For some devices which had IP but no name then it throws exception of System.Net.Sockets.SocketException: 'No such host is known'


    Darren Rose

    Wednesday, March 29, 2017 5:13 PM

  • This tool is mainly to make sure everything is up, and by use of roundtriptime/latency seeing if any areas slower to respond to help work out areas causing bottlenecks etc - currently this is done manually using command prompt and ping and helps, so a tool to do it is just automating the process


    Darren Rose

    Darren, 

    In my perception is that the maximum you can go with VB, how can you see what happens behind a switch or what a switch returns (collision information). If you want deeper, you have to check the LAN adapter data. And that is something much to deep for VB in the OS. 


    Success
    Cor

    Wednesday, March 29, 2017 5:16 PM

  • Just did it for a variety of IP addresses at home (rather than on work network) and the .HostName returned the full name of computer as I would expect

    So for my main computer which is 192.168.1.109 it returned XPSDESKTOP

    For some devices which had IP but no name then it throws exception of System.Net.Sockets.SocketException: 'No such host is known'


    Darren Rose

    Ok, I'm trying to mentally collate all of this, so I'll get started on it later before I ask any more questions. ;-)

    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Wednesday, March 29, 2017 5:21 PM

  • This tool is mainly to make sure everything is up, and by use of roundtriptime/latency seeing if any areas slower to respond to help work out areas causing bottlenecks etc - currently this is done manually using command prompt and ping and helps, so a tool to do it is just automating the process


    Darren Rose

    Darren, 

    In my perception is that the maximum you can go with VB, how can you see what happens behind a switch or what a switch returns (collision information). If you want deeper, you have to check the LAN adapter data. And that is something much to deep for VB in the OS. 


    Success
    Cor

    Fair point - though I can pull quite a lot of useful information from the System.Net.NetworkInformation namespace such as ICMP, TCPand IPv4 statistics, including errors, packet losses etc etc

    I can also use packet sniffing to get more information so can do a fair bit using VB

    Any other suggestions for tools, ways to get more information always gratefully received


    Darren Rose

    Wednesday, March 29, 2017 5:22 PM
  • Darren,

    When you get back to this, let's start with this:

    http://www.fls-online.net/VBNet_Forum/03-29-17/Test_ServerConnectivityTesting.zip

    Already there are several things to talk about, but try that when you can please.


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Wednesday, March 29, 2017 8:20 PM
  • Okay, downloaded and run - what exactly am I testing for with this version?

    Darren Rose

    Wednesday, March 29, 2017 8:42 PM
  • Okay, downloaded and run - what exactly am I testing for with this version?

    Darren Rose

    This first part is what you'll give the "process" to run (test). For each of these entries from yesterday:

    Option Strict On
    Option Explicit On
    Option Infer Off
    
    Imports ServerConnectivityTesting.ServerPing
    
    Public Class Form1
    
        Private Sub Form1_Load(sender As System.Object, _
                               e As System.EventArgs) _
                               Handles MyBase.Load
    
            Dim settings As New ServerTestSettings
    
            With settings
                .Add("192.168.10.2")
                .Add("192.168.10.3")
                .Add("192.168.2.4")
                .Add("192.168.30.5")
                .Add("192.168.0.1")
                .Add("www.pcassistonline.co.uuk")
                .Add("192.168.15.5")
                .Add("192.168.10.0")
                ' .Add("ThisWillNotWork")
            End With
    
            Stop
    
        End Sub
    End Class

    It runs through this routine that I set up for the other thread that you initially referenced.

    This is what that private function does (it's on line 246 of the class if you want to have a look):

    If the string isn't null or empty, it tries to parse it directly into an IP:

    https://msdn.microsoft.com/en-us/library/ms144109(v=vs.110).aspx

    If that fails, it [tries to] create a URI because from that I get what I need:

    https://msdn.microsoft.com/en-us/library/d6skwte6(v=vs.110).aspx

    If that fails, it internally changes the string, then once again tries to get the IP with IPAddress.TryParse.

    Finally -- if all that fails, it tries to return a value with what we talked about earlier: Dns.GetHostEntry:

    https://msdn.microsoft.com/en-us/library/ms143996(v=vs.110).aspx

    And for all of that, it will NOT throw an exception; it may return a null value though and that's where I am.

    If it's null - after trying all of that - what do you want to happen?

    Run it again and note that silently it just skipped over ".Add("www.pcassistonline.co.uuk")" and moved on, but is that what you want? If not then ... what?


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Wednesday, March 29, 2017 9:06 PM
  • Okay, I have changed some of the IP's to one I can easily test from home and run it again, and the looked at results

    Is it supposed to be picking up hostname at this stage or not? because for all of the entries it is showing no host name

    I have looked through class line 246 onwards and can see what you are doing - just not sure how much i am supposed to be able to see at this point?

    If it fails after all those checks then I suppose we either don't add it or mark it as invalid or something?

    I assume it skipped over www.pcassistonline.co.ukk because it was invalid i.e. was .ukk because I initially mistyped it? or for some other reason? I assume because mistyped because when I changed it to .uk it then shows correct IP address in the results view


    Darren Rose

    Wednesday, March 29, 2017 9:22 PM
  • Okay, I have changed some of the IP's to one I can easily test from home and run it again, and the looked at results

    Is it supposed to be picking up hostname at this stage or not? because for all of the entries it is showing no host name

    I have looked through class line 246 onwards and can see what you are doing - just not sure how much i am supposed to be able to see at this point?

    If it fails after all those checks then I suppose we either don't add it or mark it as invalid or something?

    I assume it skipped over www.pcassistonline.co.ukk because it was invalid i.e. was .ukk because I initially mistyped it? or for some other reason? I assume because mistyped because when I changed it to .uk it then shows correct IP address in the results view


    Darren Rose

    This is, right now, just a start so the answer to a lot that you asked is "I'm not there yet" (like aliasname and hostname).

    HostName will be something done only through that assembly but anyway...

    We talked earlier about doing pre-testing and I think this would be a good way to do it, but do you think that it should run it in the test anyway?

    Marking it as invalid - essentially a log - I like that idea better than skipping it because you're bound to wonder what happened, so I'll do that.

    Also, it didn't take long to go through those - including one that wouldn't pass - until it finally runs the DNS test. Add in that last one:

    .Add("ThisWillNotWork")

    It is noticeably longer and that's because it finally bumps into that last resort test (Dns.GetHostEntry).

    My question here is - should I not test that and just return null before it gets there?


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Wednesday, March 29, 2017 9:34 PM
  • Yes definitely a bit longer to run with that last one added

    Perhaps we could somehow look at it to see it is obviously not an IP address or website so that it can skip some tests knowing it can only be invalid or a host name as certainly not anything else perhaps?


    Darren Rose

    Wednesday, March 29, 2017 9:42 PM
  • Yes definitely a bit longer to run with that last one added

    Perhaps we could somehow look at it to see it is obviously not an IP address or website so that it can skip some tests knowing it can only be invalid or a host name as certainly not anything else perhaps?


    Darren Rose

    Good idea but how to do that at all, let alone faster than what I already have?

    RegEx? Aside from the fact that I don't know it - I don't know what to test for.

    If you have thoughts then let's go there -- tomorrow. It's late. ;-)


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Wednesday, March 29, 2017 9:46 PM
  • Yes the idea sounds good but how to do it I don't know off hand - will have a think and see what I can come up with

    One other thing I mentioned earlier was what if I put hostname instead of IP - what would happen - well I tried it and it is returning the IP, but it is picking up IPv6 rather than IPv4 but at least it is trying to do it that way as well


    Darren Rose

    Wednesday, March 29, 2017 10:01 PM
  • Yes the idea sounds good but how to do it I don't know off hand - will have a think and see what I can come up with

    One other thing I mentioned earlier was what if I put hostname instead of IP - what would happen - well I tried it and it is returning the IP, but it is picking up IPv6 rather than IPv4 but at least it is trying to do it that way as well


    Darren Rose

    I was going to get you to try that - but I know full well that I'm guessing my way through a lot of this, so keep that on the back burner.

    For now I'll keep it all like I have it and move forward when I can get back to it.


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Wednesday, March 29, 2017 10:05 PM
  • Thinking the other bit through some more - the fact that we have tried to check the IP with TryParse and then tried to get name with GetHostEntry - at that point I think it should then become invalid as this in reality is unlikely to happen as I would be adding the IP's, names to test so the likelihood of one of the entries being completely wrong is quite low - so probably not worth spending time working out regex or another method to check it is a valid entry or not

    Darren Rose

    Wednesday, March 29, 2017 10:29 PM
  • Thinking the other bit through some more - the fact that we have tried to check the IP with TryParse and then tried to get name with GetHostEntry - at that point I think it should then become invalid as this in reality is unlikely to happen as I would be adding the IP's, names to test so the likelihood of one of the entries being completely wrong is quite low - so probably not worth spending time working out regex or another method to check it is a valid entry or not

    Darren Rose


    You left out a step (trying to create a URI) but I'll try to do some more testing tomorrow.

    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Wednesday, March 29, 2017 11:02 PM
  • Darren,

    This is the latest build:

    http://www.fls-online.net/VBNet_Forum/03-30-17/Test_ServerConnectivityTesting.zip

    I've made several changes, starting with removing the DNS test; if it doesn't find it with all of the other stuff then [my theory is] it's not to be found.

    Also, if there's either a duplicate entry or an invalid IP string (invalid in the sense that it couldn't return an instance of IPAddress), they're logged:

    The "Add" method is overloaded now to allow you optionally give it an alias name:

    If you duplicate an alias, it has no choice but to toss it back to you:

    As you can see, the purpose of this part is that per entry (per IP), it has all of the settings needed, but I have it set up so that if you want to use the defaults then you don't need to tell it to that. With 50 of them, that's bound to help:

    As an example:

    When you can, how about try it using whatever ones you want to test it with and let me know please.


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Thursday, March 30, 2017 1:33 PM
  • That all seems okay apart from one question - if I amend the website url to be correct e.g. change .ukk to .uk it still doesn't add it to the list?

    Darren Rose

    Thursday, March 30, 2017 1:47 PM
  • That all seems okay apart from one question - if I amend the website url to be correct e.g. change .ukk to .uk it still doesn't add it to the list?

    Darren Rose

    That's not good.

    I'll have a look and see.


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Thursday, March 30, 2017 1:57 PM
  • Darren,

    I'm glad that you tested it for this. On lines 358 and 359, please uncomment out the code and rebuild it:

    Dim entry As IPHostEntry = Dns.GetHostEntry(ipString)
    retVal = entry.AddressList(0)

    So much for thinking that the Dns test was worthless...


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Thursday, March 30, 2017 2:01 PM
  • Yes that sorted it

    Darren Rose

    Thursday, March 30, 2017 2:11 PM
  • Yes that sorted it

    Darren Rose

    At the expense of being noticeably slower though.

    I'll continue on unless you have an idea of how else to figure out the bad ones?


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Thursday, March 30, 2017 2:13 PM
  • Yes that sorted it


    Darren Rose

    At the expense of being noticeably slower though.

    I'll continue on unless you have an idea of how else to figure out the bad ones?


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    To be honest with just one web address it wasn't that much slower and I doubt I will have many - mostly will be internal IP's

    I had a play around with regex and googled some other ideas re figuring out bad ones but it gets really complex and with so many possible permutations of domain names I think best to put up with slight delay - as I say I will be adding the list of addresses so unlikely to be a) any wrong or b) many websites anyway


    Darren Rose

    Thursday, March 30, 2017 2:16 PM

  • To be honest with just one web address it wasn't that much slower and I doubt I will have many - mostly will be internal IP's

    I had a play around with regex and googled some other ideas re figuring out bad ones but it gets really complex and with so many possible permutations of domain names I think best to put up with slight delay - as I say I will be adding the list of addresses so unlikely to be a) any wrong or b) many websites anyway


    Darren Rose

    I'll get back to this when I can then.


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Thursday, March 30, 2017 2:20 PM
  • Darren,

    I do have some work-related stuff that I need to take care of but I wanted to get this part done, or at least reasonably close.

    I've added a method to export the data to an XML file and another to import it back in:

    http://www.fls-online.net/VBNet_Forum/03-30-17/TestMe.xml

    I want to point this out and get your feedback. It doesn't keep up with the ip strings that were either duplicates or invalid:

    They're not there because they weren't in the internal collection, but is that a problem? Should they be persisted?


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Thursday, March 30, 2017 3:23 PM
  • No I don't think it is a problem - if duplicate or invalid then they don't need to be persisted as far I can see


    Darren Rose

    Thursday, March 30, 2017 3:31 PM
  • No I don't think it is a problem - if duplicate or invalid then they don't need to be persisted as far I can see


    Darren Rose

    Ok, good then.

    I'd like to get you to try something: You said yesterday that the IP of "MailServer" (I think it was that) was the wrong one? Do keep in mind that I'm as ignorant as can be about most of this.

    What I wanted you to do is to take that IP and try it in the test routine that you showed the other day and see what it does?

    I'm just curious really.


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Thursday, March 30, 2017 3:35 PM
  • Yes Dns.GetHostEntry was returning the IPv6 address rather than the IPv4 address

    I can confirm pinging the IPv6 address it returned does work though

    But if possible I would prefer to get the IPv4 address as I/we and most people I know don't really use IPv6 addresses and the are a lot more complicated to remember

    e.g. fe80::698f:a5c0:ce0:35dc%16 instead of 192.168.1.109

    ***

    When Dns.GetHostEntry checks the entry - each item it finds has a property of AddressFamily - if this is InterNetworkV6 then it is an IPv6 address - if it is InterNetwork then it is the correct IPv4 address we need

    In a quick bodge of your code I added in the bit below to check the AddressFamily and only add it if IPv4 - probably a better way of coding it, but at least it shows the correct result

    Dim entry As IPHostEntry = Dns.GetHostEntry(ipString)
           For Each address As IPAddress In entry.AddressList
              If (address.AddressFamily = Sockets.AddressFamily.InterNetwork) Then
                  retVal = address
              End If
           Next


    Darren Rose

    Thursday, March 30, 2017 4:15 PM
  • Darren,

    I'm impressed with how much you know about this stuff - and I'll say again, I don't!

    ;-)

    *****

    I can add that code in, but what if it never gets that far?


    "A problem well stated is a problem half solved.” - Charles F. Kettering


    Thursday, March 30, 2017 4:21 PM
  • Networking was what I started out doing, can't say I enjoy it but its handy to know - and certainly proving useful now :)   

    Its nice that I can actually help properly for a change rather than relying on your skills!

    From the tests I did I think it would always get to that step if it was just a hostname I provide? as if IP address I supply then it will already be IPv4, and if website address then it would get returned as IPv4 anyway I believe - so unless I am missing something then it should be okay - will test more as we progress though


    Darren Rose

    Thursday, March 30, 2017 4:25 PM
  • Networking was what I started out doing, can't say I enjoy it but its handy to know - and certainly proving useful now :)   

    Its nice that I can actually help properly for a change rather than relying on your skills!

    From the tests I did I think it would always get to that step if it was just a hostname I provide? as if IP address I supply then it will already be IPv4, and if website address then it would get returned as IPv4 anyway I believe - so unless I am missing something then it should be okay - will test more as we progress though


    Darren Rose

    It's interesting - I always learn from these.

    Should that addenda be optional, defaulted to true maybe? If so, what should I call the variable that sets it?


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Thursday, March 30, 2017 4:40 PM
  • Not sure if it really needs to be optional - as would never need to find IPv6 addresses so probably not worth doing

    Darren Rose

    Thursday, March 30, 2017 4:46 PM
  • Not sure if it really needs to be optional - as would never need to find IPv6 addresses so probably not worth doing

    Darren Rose

    This is what I changed it to, but let's be sure we're on the same track here:

    Dim entry As IPHostEntry = Dns.GetHostEntry(ipString) retVal = (From address As IPAddress In entry.AddressList _ Where address.AddressFamily = Sockets.AddressFamily.InterNetwork).FirstOrDefault


    I've said before that if you use .FirstOrDefault, to be sure to test that it's not null before you use it but that doesn't apply anyway - not here:

    Dim retVal As IPAddress = Nothing

    In yours, you have a loop and that's fine, but think about something:

    For Each address As IPAddress In entry.AddressList If (address.AddressFamily = Sockets.AddressFamily.InterNetwork) Then retVal = address End If Next


    If it finds it then set retVal and exit the loop at that point:

           For Each address As IPAddress In entry.AddressList
              If (address.AddressFamily = Sockets.AddressFamily.InterNetwork) Then
                  retVal = address
                  Exit For
              End If
           Next

    The linq part above is doing the same thing and I take the first one OR the default (which might be null).

    I assume that's what you mean with this, right? The first one that matches the criteria (if any)?


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Thursday, March 30, 2017 5:05 PM
  • Yes that's perfect - just tested it and works fine

    I knew there would be a better/cleaner way of doing it, my attempt was just quick to see if my logic worked


    Darren Rose

    Thursday, March 30, 2017 5:11 PM
  • Yes that's perfect - just tested it and works fine

    I knew there would be a better/cleaner way of doing it, my attempt was just quick to see if my logic worked


    Darren Rose

    Ok good. Here's the latest:

    http://www.fls-online.net/VBNet_Forum/03-30-17/Test_ServerConnectivityTesting_Revised.zip

    I'll be back tomorrow and start on the next part but please test that every way you can think of to see if there's something that I missed in it.


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Thursday, March 30, 2017 5:19 PM
  • Okay I will test it thoroughly later and report back

    I have found one problem already though:-

    I added a computer by IP address (192.168.1.109) and also added it by hostname (XPSDESKTOP) - it has obviously resolved the name to IP and therefore we end up with a duplicate as 192.168.1.109 is in results twice


    Darren Rose

    Thursday, March 30, 2017 5:35 PM
  • Okay I will test it thoroughly later and report back

    I have found one problem already though:-

    I added a computer by IP address (192.168.1.109) and also added it by hostname (XPSDESKTOP) - it has obviously resolved the name to IP and therefore we end up with a duplicate as 192.168.1.109 is in results twice


    Darren Rose

    Ah ok - I never thought about that. Right now it's just looking at duplicate strings in the .Add method.

    I'll work on that tomorrow then.


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Thursday, March 30, 2017 5:41 PM
  • Frank

    Just been putting some more thought to something I said earlier re two different tests/uses for this class e.g.

    1) First one where you run and it loops x times to show results in a table/grid/list whatever I/we use - so I can see name(alias or hostname), IP address, status (up/down etc), and average/min/max for roundtriptime/latency - basically as initially discussed

    2) Then for second one I said about leaving it running for longer to get information and if so it then "pings" less often but over a longer time period say perhaps 24 hours. 

    I then thought why would this be much use as seeing results in a grid in same way but over a longer period wouldn't tell me anything useful.

    But if I could ping each address in list and get current results say every 15 minutes and then store it somehow with date/time as well then after say 24 hours I could load output into Excel or similar and easily see trends of when network was slower/faster and easily see what time of day it happened

    Just a thought as would make tool so much more useful in long run - and hopefully doesn't really have too much bearing on what we/you have done so far? and if not possible don't worry just my head has been spinning ideas this evening so thought I would voice them


    Darren Rose

    Thursday, March 30, 2017 7:08 PM
  • Frank

    Just been putting some more thought to something I said earlier re two different tests/uses for this class e.g.

    1) First one where you run and it loops x times to show results in a table/grid/list whatever I/we use - so I can see name(alias or hostname), IP address, status (up/down etc), and average/min/max for roundtriptime/latency - basically as initially discussed

    2) Then for second one I said about leaving it running for longer to get information and if so it then "pings" less often but over a longer time period say perhaps 24 hours. 

    I then thought why would this be much use as seeing results in a grid in same way but over a longer period wouldn't tell me anything useful.

    But if I could ping each address in list and get current results say every 15 minutes and then store it somehow with date/time as well then after say 24 hours I could load output into Excel or similar and easily see trends of when network was slower/faster and easily see what time of day it happened

    Just a thought as would make tool so much more useful in long run - and hopefully doesn't really have too much bearing on what we/you have done so far? and if not possible don't worry just my head has been spinning ideas this evening so thought I would voice them


    Darren Rose

    Actually, that might simplify things because the next part will now just have one mode: "Run the tests and let me know the results when you're done".

    After that, a way to repeat them based on some frequency will still just run that one test again (assuming it's not still running).

    I think. ;-)

    Does that sound like something you have in mind?


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Thursday, March 30, 2017 7:28 PM
  • Yes that sounds about right - it would be exact same test, pinging same list of servers, only difference would be interval between pings (frequency) and how the data is outputted / stored - so for quick test it would just show in form and for long test it would be stored along with date/time of each ping for later analysis


    Darren Rose

    Thursday, March 30, 2017 7:44 PM
  • Yes that sounds about right - it would be exact same test, pinging same list of servers, only difference would be interval between pings (frequency) and how the data is outputted / stored - so for quick test it would just show in form and for long test it would be stored along with date/time of each ping for later analysis


    Darren Rose


    When I can get back to this, I'll work through all of this. I also have a few things to change to the first part, but I'll get to it, hopefully tomorrow.

    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Thursday, March 30, 2017 7:57 PM
  • Darren,

    I won't be back until this afternoon, but I was thinking about something earlier:

    In this first part should I have another optional parameter for the minimum amount of time to lapse before subsequent hits? What I was asking Reed the other day about how to avoid the server thinking that it might be a DoS attack?

    If you want it to always be the same, I can do that in the next part, but if you want to set it differently per IP, this is the place to do it.


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Friday, March 31, 2017 11:35 AM
  • Hi Frank

    No problem

    The minimum amount of time to wait as per Reeds comments would be the same for all IP, so doesn't need to be per IP - BUT I would need ability to change it, as per my post about two different scans, one would me a quick check so that delay would need to be as Reed suggested enough to not make it think is a DoS attack - for the second scan where I leave it running all day say then the amount of time between each set of pings would be say 15 minutes or 30 minutes or so


    Darren Rose

    Friday, March 31, 2017 12:11 PM
  • Darren,

    Try the latest build please:

    http://www.fls-online.net/VBNet_Forum/03-31-17/Test_ServerConnectivityTesting.zip

    I'm not sure that I'm following you about the scan time, but I'll try to test things over the weekend and see if I can come up with a better plan.

    For this, how about check to see if it effectively finds the duplicate entry.


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Friday, March 31, 2017 6:41 PM
  • Hi Frank

    Yes I can confirm it does find the duplicate entry now

    I will try and explain further:-

    Lets say we have 10 IP addresses in list

    So for main test I would ping all 10 addresses every x seconds (whatever Reed suggested was okay) and repeat it 20 times and get average/max/min - so could see any area where slow at that time

    For long test I would ping all 10 addresses every 15 minutes (or 30 minutes) for 24 hours so I could then analyze results in Excel to see what times of day it was slower/faster, see any trends etc


    Darren Rose

    Friday, March 31, 2017 6:56 PM

  • Lets say we have 10 IP addresses in list

    So for main test I would ping all 10 addresses every x seconds (whatever Reed suggested was okay) and repeat it 20 times and get average/max/min - so could see any area where slow at that time

    For long test I would ping all 10 addresses every 15 minutes (or 30 minutes) for 24 hours so I could then analyze results in Excel to see what times of day it was slower/faster, see any trends etc


    Darren Rose

    Well, now we're back to the issue of intermediate results.

    What would be wrong with setting up a test which would consist of the 10 addresses, repeating until it's completed? Completed being that all IP's have been tested the requisite number of times. At that point, you'll have the results.

    Later, for the long test, there would be some sort of scheduler (not sure on specifics) that would run that same test - wait 30 minutes and repeat, continuing until it was told to stop.

    Something like that?


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Friday, March 31, 2017 7:02 PM
  • Yes that makes sense - so one test and we either run it once (being 10 addresses x times) or we repeat same test every 30 mins - yes agree with that

    Darren Rose

    Friday, March 31, 2017 7:44 PM
  • Yes that makes sense - so one test and we either run it once (being 10 addresses x times) or we repeat same test every 30 mins - yes agree with that

    Darren Rose

    Good - and who knows what it will end up being or doing, but I think it'll simplify it all.

    *****

    I think I'll take a short hiatus from this and look at it more over the weekend.


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Friday, March 31, 2017 7:50 PM
  • I think I'll take a short hiatus from this and look at it more over the weekend.


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Okay no problem

    Darren Rose

    Friday, March 31, 2017 7:52 PM
  • I flubbed that up. I'll be back with a corrected one in a while.

    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Saturday, April 01, 2017 12:21 PM
  • Darren,

    Try this version please:

    http://www.fls-online.net/VBNet_Forum/04-01-17/Test_ServerConnectivityTesting_V2.zip

    Specifically test it for it finding the HostName (if there's one to be had).


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Saturday, April 01, 2017 12:49 PM
  • Hi Frank,

    Yes it does successfully get the HostName and very quickly if the IP I add are all working/up

    But with the default list where lots of them don't exist then it takes quite a while to get to the stop line - not necessarily a problem as most time the IP would always exist that I use

    Tried adjusting timeout from 3000 to 1000 but didn't seem to make any difference?


    Darren Rose

    Saturday, April 01, 2017 1:10 PM
  • Hi Frank,

    Yes it does successfully get the HostName and very quickly if the IP I add are all working/up

    But with the default list where lots of them don't exist then it takes quite a while to get to the stop line - not necessarily a problem as most time the IP would always exist that I use

    Tried adjusting timeout from 3000 to 1000 but didn't seem to make any difference?


    Darren Rose

    If you mean the optional parameter, that's for the test (the next part). If that's not what you mean then please show me what you set?


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Saturday, April 01, 2017 1:29 PM
  • If you mean the optional parameter, that's for the test (the next part). If that's not what you mean then please show me what you set?

    Yes ignore me I realised that after I had tried it and posted!

    Darren Rose


    • Edited by wingers Saturday, April 01, 2017 1:37 PM
    Saturday, April 01, 2017 1:31 PM
  • I think it is something that we will just have to live with, as seems no other way to do it - if all IP addresses valid and online then it is very quick, only slow when trying to gethostname from an IP which is not available at that point

    Darren Rose

    Saturday, April 01, 2017 1:39 PM
  • I think it is something that we will just have to live with, as seems no other way to do it - if all IP addresses valid and online then it is very quick, only slow when trying to gethostname from an IP which is not available at that point

    Darren Rose


    Ok, I'll start on the next part and see where that goes.

    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Saturday, April 01, 2017 1:48 PM
  • FWIW - I have this class that pings one device and keeps stats on it.  It makes extensive use of threads(Tasks).  The pings and name resolution are ran on threads.

    Don't know if it will help because this thread is really long and I just started from the tail end.

    Public Class PingDevice
        Public Event PingErrored(device As PingDevice)
        Public ThisIP As Net.IPAddress
        Public FQDN As String = ""
        Public TimeOut As Integer = 250
        ''' <summary>
        ''' if true device will be pinged
        ''' </summary>
        ''' <remarks></remarks>
        Public isPinging As Boolean = False
        Private isRunning As New Threading.ManualResetEvent(True)
        Private isStopping As New Threading.ManualResetEvent(False)
        Public PingEvery As New TimeSpan(0, 0, 15) 'ping device every ... default is 15 seconds
        Public LastPingReply As Net.NetworkInformation.PingReply
        Public LastPingAttempt As DateTime
    
        ''' <summary>
        ''' device with ip address
        ''' </summary>
        ''' <param name="ip">the ip address of the device</param>
        ''' <param name="start">start pinging. if false then set isPinging to true manually</param>
        ''' <remarks></remarks>
        Public Sub New(ip As Net.IPAddress, Optional start As Boolean = False)
            Me.ThisIP = ip
            Me.FQDN = Me.ThisIP.ToString
            Me.StartPing(start)
        End Sub
    
        ''' <summary>
        ''' either a name or an ip address as string
        ''' </summary>
        ''' <param name="name">name or an ip address as string</param>
        ''' <param name="start">start pinging. if false then set isPinging to true manually</param>
        ''' <remarks></remarks>
        Public Sub New(name As String, Optional start As Boolean = False)
            Me.FQDN = name
            Me.StartPing(start)
        End Sub
    
        ''' <summary>
        ''' stop the ping and clear variables.  call before setting instance to nothing
        ''' </summary>
        ''' <remarks></remarks>
        Public Sub EndPing()
            If Me.isStopping Is Nothing Then Exit Sub
            Me.isStopping.Set()
            Do While Me.isRunning.WaitOne(0) 'wait for DoPingLoop to end
                Threading.Thread.Sleep(250)
            Loop
            Me.isStopping = Nothing
            Me.isRunning = Nothing
            Me.pingTask = Nothing
            Me.PingSpecificErrors.Clear()
            Me.PingTimes.Clear()
            Me.PingSpecificErrors = Nothing
            Me.PingTimes = Nothing
        End Sub
    
        Public Function Match(otherDevice As PingDevice) As Boolean
            Dim rv As Boolean = False
            If Me.ThisIP Is Nothing AndAlso otherDevice.ThisIP Is Nothing Then
                rv = True
            ElseIf Me.ThisIP Is Nothing OrElse otherDevice.ThisIP Is Nothing Then
                rv = False
            Else
                rv = Me.ThisIP.ToString = otherDevice.ThisIP.ToString
            End If
            Return rv
        End Function
    
        Private pingTask As Task
        Private Sub StartPing(start As Boolean)
            If start Then Me.isPinging = True
            For Each st As String In [Enum].GetNames(GetType(Net.NetworkInformation.IPStatus))
                Me.PingSpecificErrors.Add(st, 0L)
            Next
            Me.PingSpecificErrors.Add(Me.PingThrewError, 0L)
            Me.pingTask = New Task(AddressOf Me.DoPingLoop)
            Me.pingTask.Start()
        End Sub
    
        Private Sub DoPingLoop()
            Dim getThis As String
            Do
                If Me.isPinging Then
                    If Me.ThisIP Is Nothing Then
                        If Net.IPAddress.TryParse(Me.FQDN, Me.ThisIP) Then
                            'FQDN is IP address
                            getThis = Me.ThisIP.ToString
                        Else
                            getThis = Me.FQDN
                        End If
                    Else
                        getThis = Me.ThisIP.ToString
                    End If
                    If (Me.ThisIP Is Nothing OrElse Me.FQDN = Me.ThisIP.ToString) Then
                        'name not resolved
                        Me.NameResolution(getThis)
                    End If
                    If Me.ThisIP IsNot Nothing Then
                        'do ping
                        Me.DoPing()
                        'Else
                        'Debug.WriteLine(getThis)
                    End If
                End If
                If Me.isStopping.WaitOne(Me.PingEvery) Then Exit Do
            Loop While Me.isRunning.WaitOne(0)
            Me.isRunning.Reset()
        End Sub
    
        Private PingThrewError As String = "PingThrewError"
        Public PingsSent As Long = 0L
        Public PingTotalErrorCount As Long = 0L
        Public PingSpecificErrors As New Dictionary(Of String, Long)
        Public AverageRTT As Double = -1.0R
        Public AvgSamples As Integer = 500
        Public MaxRTT As Long = Long.MinValue
        Public MinRTT As Long = Long.MaxValue
        Private PingTimes As New List(Of Long)
        Private Sub DoPing()
            Dim pinger As New Net.NetworkInformation.Ping
            Dim pingopt As New Net.NetworkInformation.PingOptions(30, True)
            Dim b(1) As Byte
            Dim errct As Long = Me.PingTotalErrorCount
            Try
                Me.PingsSent += 1
                Me.LastPingAttempt = DateTime.Now
                Me.LastPingReply = pinger.Send(Me.ThisIP, Me.TimeOut, b, pingopt)
                Me.PingSpecificErrors(Me.LastPingReply.Status.ToString) += 1L
                If Me.LastPingReply.Status = Net.NetworkInformation.IPStatus.Success Then
                    Me.PingTimes.Add(Me.LastPingReply.RoundtripTime)
                    Me.AverageRTT = Me.PingTimes.Average
                    If Me.PingTimes.Count > Me.AvgSamples Then
                        Me.PingTimes.RemoveRange(0, Me.AvgSamples \ 2)
                        Me.PingTimes.Add(CLng(Me.AverageRTT))
                    End If
                    If Me.LastPingReply.RoundtripTime > Me.MaxRTT Then Me.MaxRTT = Me.LastPingReply.RoundtripTime
                    If Me.LastPingReply.RoundtripTime < Me.MinRTT Then Me.MinRTT = Me.LastPingReply.RoundtripTime
                Else
                    Me.PingTotalErrorCount += 1L
                End If
            Catch ex As Exception
                Me.PingSpecificErrors(Me.PingThrewError) += 1L
                Me.PingTotalErrorCount += 1L
            End Try
            If errct <> Me.PingTotalErrorCount Then
                RaiseEvent PingErrored(Me)
            End If
        End Sub
    
        Public Resolve As Boolean = True
        Private Sub NameResolution(name As String)
            If Not Me.Resolve Then Exit Sub
            Static tskR As Task
            If tskR IsNot Nothing AndAlso tskR.Status <> TaskStatus.RanToCompletion Then
                Exit Sub
            End If
            tskR = Task.Run(Sub()
                                Try
                                    Dim host As Net.IPHostEntry = Net.Dns.GetHostEntry(name)
                                    If host.AddressList IsNot Nothing AndAlso host.AddressList.Count > 0 Then
                                        If Me.ThisIP Is Nothing Then
                                            Me.ThisIP = host.AddressList(0)
                                        Else
                                            Me.FQDN = host.HostName
                                        End If
                                    End If
                                Catch ex As Exception
                                    'ignore
                                End Try
                            End Sub)
            tskR.Wait(10)
        End Sub
    
        Public Shared Function IPtoNum(ipAddr As Net.IPAddress) As Integer
            Dim b() As Byte = ipAddr.GetAddressBytes
            Array.Reverse(b)
            Dim rv As Integer = BitConverter.ToInt32(b, 0)
            Return rv
        End Function
    
        Public Shared Function NumToIP(ipAddr As Integer) As Net.IPAddress
            Dim rv As Net.IPAddress
            Dim b() As Byte = BitConverter.GetBytes(ipAddr)
            Array.Reverse(b)
            rv = New Net.IPAddress(b)
            Return rv
        End Function
    
        Public Shared Function IPList(startIP As Net.IPAddress, endIP As Net.IPAddress) As List(Of Net.IPAddress)
            Dim sip As Integer = IPtoNum(startIP)
            Dim eip As Integer = IPtoNum(endIP)
            Dim tip As Integer
            If sip > eip Then
                'exchange
                tip = sip
                sip = eip
                eip = tip
            End If
            Dim rv As New List(Of Net.IPAddress)
            For tip = sip To eip
                Dim ip As Net.IPAddress = NumToIP(tip)
                rv.Add(ip)
            Next
            Return rv
        End Function
    
        Public Shared Function IPList(startIP As Net.IPAddress, cidr As Integer) As List(Of Net.IPAddress)
            Dim cidrMask As Integer
            If cidr >= 8 AndAlso cidr <= 31 Then
                cidrMask = &H80000000 >> (cidr - 1) 'create the mask, shift smears sign
            Else
                cidrMask = &H80000000 >> (16 - 1) 'def. cidr of 16
            End If
            Dim sip As Integer = IPtoNum(startIP)
            Dim eip As Integer
            Dim tip As Integer
            sip = sip And cidrMask 'start ip
            eip = sip Xor (cidrMask Xor -1) 'end ip
            Dim rv As New List(Of Net.IPAddress)
            For tip = sip To eip
                Dim ip As Net.IPAddress = NumToIP(tip)
                rv.Add(ip)
            Next
            Return rv
        End Function
    End Class

    simple usage example

        Dim monitor As New List(Of PingDevice)
        Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
            Dim ip As Net.IPAddress = Net.IPAddress.Parse("192.168.1.1")
            Dim lip As List(Of Net.IPAddress) = PingDevice.IPList(ip, 29)
            monitor = New List(Of PingDevice)
            For Each ip In lip
                monitor.Add(New PingDevice(ip, True))
                Threading.Thread.Sleep(10)
            Next
        End Sub

    results

            For Each pd As PingDevice In monitor
                Debug.WriteLine("{0} {1} {2}", pd.FQDN, pd.PingTotalErrorCount, pd.AverageRTT)
            Next


    "Those who use Application.DoEvents() have no idea what it does and those who know what it does never use it." - MSDN User JohnWein    Multics - An OS ahead of its time.








    • Edited by dbasnett Sunday, April 02, 2017 1:54 PM
    Saturday, April 01, 2017 4:24 PM
  • I think it is something that we will just have to live with, as seems no other way to do it - if all IP addresses valid and online then it is very quick, only slow when trying to gethostname from an IP which is not available at that point


    Darren Rose


    Ok, I'll start on the next part and see where that goes.

    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Okay excellent

    On the host name bit - perhaps we can have this as an option defaulted to true so if for some reason I didn't want to retrieve hostname I can set it to false and show the alias name instead


    Darren Rose

    Saturday, April 01, 2017 5:01 PM
  • db,

    You're right about the thread being long. ;-)

    Thanks for the information - I'm a good ways into this right now, so looking at doing it all another way would confuse things, but I have no doubt that you know what you're doing with all this.


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Saturday, April 01, 2017 5:27 PM

  • On the host name bit - perhaps we can have this as an option defaulted to true so if for some reason I didn't want to retrieve hostname I can set it to false and show the alias name instead


    Darren Rose

    I'll do that before I re-submit.

    I'm trying to work out the testing and I lucked up in that one that I tested is legit, but it won't return a value from the test (it times out). That made me think of just how to handle it all.


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Saturday, April 01, 2017 5:29 PM
  • Darren,

    I'd like to explain what I have then ask a question. I used the following for this test:

    .Add("google.com")
     ' .Add("192.168.10.3")
    .Add("youtube.com")
    .Add("facebook.com")
    .Add("wikipedia.org")
    .Add("yahoo.com")
    .Add("amazon.com")
    .Add("twitter.com")
    .Add("reddit.com")

    The one commented out (which is a fake one) was for part of the test, but the following relates to the eight others.

    I have a private class (several, actually) which has all of the IP's and settings per IP. Along with that though, there's a nullable of DateTime and a boolean property named "Completed".

    The logic works like this:

    Do Dim qry As System.Collections.Generic.IEnumerable(Of ServerTestTimes) = _ From stt As ServerTestTimes In hitTimesList _ Where Not stt.Finished If qry.Count = 0 Then Exit Do Else Beep() End If For Each stt As ServerTestTimes In hitTimesList _currentServerName = stt.DisplayName If Not stt.Finished Then Dim proceed As Boolean = False If stt.NextHitDateTime.HasValue Then If Now >= stt.NextHitDateTime.Value Then proceed = True End If Else proceed = True End If If proceed Then Dim result As LocalTestResults = GetTestResults(stt.Item) ltrList.Add(result) stt.AddHit(hitTimesList, stt.IpString) stt.SetNextHitTime(hitTimesList, stt.IpString, Now.AddMilliseconds(params.MinimumLapseMilliseconds)) _currentLoopCount += 1 End If End If Next Threading.Thread.Sleep(100) Loop


    The "beep" is just so that I could tell what was going on. If it weren't for the timeout, what you see above would be dangerous - it may never exit the Do.

    It runs through the eight the first time (because the nullable doesn't have value). As it proceeds though, each of them (in the private class) gets the next hit datetime based on the class-scoped variable "MinimumLapseMilliseconds". That defaults to 2000 but since I set it after it returns, it's actually a bit longer than two seconds so I feel sure that it's met the minimum.

    Now it returns to the top and, per IP, looks to see if "NextHitDateTime" has value and, if so, if "Now" is greater than or equal to it.

    To keep it from running through so fast, I have it pausing for a tenth of a second at the end. It then runs through until all of them are complete and that's where I am in what you see here:

    Per instance, this is what I have it returning:

    Now some questions: For "name", is what you see in the last screenshot ok or do you want the IP address (.ToString) separate?

    Let me know if you follow all of that then I'll ask the second question.


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Sunday, April 02, 2017 12:36 PM
  • Hi Frank

    Yes that make sense

    For name I would prefer IP separate, and if possible Alias and Host separate, so I can then do something like if host is nothing show alias, or if host contains something then show it instead of alias perhaps as wouldn't need to show both

    EDIT or if I had used alias to show a more detailed name then I could show both

    Question - so the RoundTripMillieseconds of 22 shown in second image - is that the average of all loops, or just the value from that one test?


    Darren Rose


    • Edited by wingers Sunday, April 02, 2017 12:44 PM edit
    Sunday, April 02, 2017 12:43 PM
  • Hi Frank

    Yes that make sense

    For name I would prefer IP separate, and if possible Alias and Host separate, so I can then do something like if host is nothing show alias, or if host contains something then show it instead of alias perhaps as wouldn't need to show both

    EDIT or if I had used alias to show a more detailed name then I could show both

    Question - so the RoundTripMillieseconds of 22 shown in second image - is that the average of all loops, or just the value from that one test?


    Darren Rose


    What you see shown is an internal private class so you'll never see any of that. I'm in the process of putting together the public class and that leads to this:

    You said the other day:

    name, IP address, status (up/down), average roundtrip, max roundtrip, min roundtrip

    I'll make sure it can give you each of the three (IP, Alias, Hostname) separately but to the other qustions:

    The aggregate is all that you want, correct? Not each individual test result (which is what's shown in the last screenshot).

    At some point we have to reconcile this:

    What if the status differs? In that one above there are eight IPs and ten loops each. I can't assume that the status (per IP) of all ten are the same so how do you want to handle that?


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Sunday, April 02, 2017 12:51 PM
  • Thanks

    Okay this bits needs some thought then - as yes for the "quick" test I keep referring too all I would want to be able to show is name and/or alias, IP address, status, average/min/max roundtrip as you mention above

    For the "long" test then I would like if possible to have some sort of access to the full data somehow - as what I envisage doing is running it for 24 hours perhaps, so it would do (using example above) ten loops of eight IP's and it would repeat that test every 30 minutes - so at the end I could have all the data with time of test as well for each IP and then in excel I could analyse it to see trends such as sorting by max roundtrip to see when it happened and then if I did test another day I could see if happening same time each day - does that make sense? don't worry if not possible or needs to be done differently, willing to take all your advice on this

    Status:

    My way of thinking would be this - if the status for an IP was "down" for all 10 ten loops then result would be down, if it was only down for 1 out of 10 or something then result would be up as we would still have usable min/max/average values


    Darren Rose

    Sunday, April 02, 2017 1:09 PM
  • Thanks

    Okay this bits needs some thought then - as yes for the "quick" test I keep referring too all I would want to be able to show is name and/or alias, IP address, status, average/min/max roundtrip as you mention above

    For the "long" test then I would like if possible to have some sort of access to the full data somehow - as what I envisage doing is running it for 24 hours perhaps, so it would do (using example above) ten loops of eight IP's and it would repeat that test every 30 minutes - so at the end I could have all the data with time of test as well for each IP and then in excel I could analyse it to see trends such as sorting by max roundtrip to see when it happened and then if I did test another day I could see if happening same time each day - does that make sense? don't worry if not possible or needs to be done differently, willing to take all your advice on this

    Status:

    My way of thinking would be this - if the status for an IP was "down" for all 10 ten loops then result would be down, if it was only down for 1 out of 10 or something then result would be up as we would still have usable min/max/average values


    Darren Rose

    Long and short will all be the same (unless you change the settings). "A test consists of"... and that's what I'm working on. Later we'll look at constructing something that calls this test every x minutes or whatever, but making this part the same for everything will simplify it all.

    *****

    What I'm returning (inside, my private classes) is the actual status: The IPStatus. If you want though, I can have a tri-state enum of our own:

    Up
    Down
    Mixed

    Something like that maybe? If you want to eliminate "Mixed" then I'll have to make sure that the number of loops is an odd number.


    "A problem well stated is a problem half solved.” - Charles F. Kettering


    • Edited by Frank L. Smith Sunday, April 02, 2017 1:16 PM ...added link to MSDN documentation
    Sunday, April 02, 2017 1:15 PM
  • Long and short will all be the same (unless you change the settings). "A test consists of"... and that's what I'm working on. Later we'll look at constructing something that calls this test every x minutes or whatever, but making this part the same for everything will simplify it all.

    Okay that's fine

    Thinking it through some more - perhaps we can do this so the class does the analyzing for me - rather than me needing all data to export to excel?

    As the main and only thing I would be looking for in a long test is when the max roundtrip happens to look for trends - so if perhaps somehow we can store time of max value occurring for each IP address then we would have all the info needed for both long/short in the one part

    Then if say I ran it on a Thursday and I could see roundtrip for server1 was high at 17:00, I could then run long test another day and see if same server was high as same time - i.e. giving me a trend to investigate as what that server does at 17:00 which could be slowing down the network

    If I can get max roundtrip value and WHEN it occurred for each IP then no further analysis needed

    What I'm returning (inside, my private classes) is the actual status: The IPStatus. If you want though, I can have a tri-state enum of our own:

    Up
    Down
    Mixed

    Something like that maybe? If you want to eliminate "Mixed" then I'll have to make sure that the number of loops is an odd number.


    Okay actually knowing the full value from IPStatus could be useful then, as then I would know reason it couldn't contact one of the IP's in the list rather than just getting "Down"

    So therefore showing that full value in returned information would be fine, as if it managed to ping a couple of times out of the ten loops we would still get some resulting data - but I could then see from status it was incomplete as instead of saying "Success" it would say  the failure reason


    Darren Rose

    Sunday, April 02, 2017 1:27 PM
  • Darren,

    I agree with what you said there and I can manage the "when" for min and max.

    Where I'm still lost though is how to show the status in the public class unless I group them by status (if there's more than one).

    Agree?


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Sunday, April 02, 2017 1:45 PM
  • Excellent

    What sort of status results are you seeing during testing? as I would expect you would normally only see Success or 1 of the error messages? so if  all 10 loops per IP were Success then show success, but if any of the loops were not success then show the error message? Or are you seeing more than one different error message per loop?


    Darren Rose

    Sunday, April 02, 2017 1:50 PM
  • Excellent

    What sort of status results are you seeing during testing? as I would expect you would normally only see Success or 1 of the error messages? so if  all 10 loops per IP were Success then show success, but if any of the loops were not success then show the error message? Or are you seeing more than one different error message per loop?


    Darren Rose

    This is what I now have it returning (keep in mind this is the private class):

    With that, I'll have what I need.

    So far I've only seen one of two: Success or TimedOut. It's not (so far) thrown an exception.

    Do you want me to package this up and you try it on your end with the 'real' ones? If so, I'll temporarily put something in it to show you the returned status(es).


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Sunday, April 02, 2017 1:59 PM
  • Yes please - would be handy for me to test it now then I can let you know what statuses I get back

    ****

    Going back to the short test / long test scenario - I just wanted to make a comment/suggestion in case this changes anything at this stage

    Being able to return the "when" for min/max for each IP is going to be very handy for long test and will have this doing all I need and more

    But imagine this, if we ran test once (short test) so say 10 repetitions of 8 IP addresses we would then get all results back and that would be great

    If we then wanted to do (long test) and again say 10 reps of 8 IP's  and repeat it every 30 minutes for 24 hours (lets call them sets) would we get max when for min/max for each rep or for the full set (e.g. after running 24 hours) - as I need the result at end of whole test (set) rather than for each rep

    So using an exercise analogy perhaps we need to be able to pass to the class the following information:-     

    number of reps - e.g. how many times to repeat/loop through each IP

    number of sets - e.g. how many times to repeat the above reps

    delay between sets - e.g. 30 minutes or 60 minutes

    So for a short test you would pass 10 reps / 1 set and delay not relevant - and it would return results as discussed

    And for long test we would pass 10 reps / 48 sets and delay 30 minutes (which would give 24 hours approx of testing) - and at end it would return cumulative result for all that period i.e. one result not 48 sets of results

    That way one class would do everything and just what we call it with determines if short or long test

    Hope that makes sense?!??!!


    Darren Rose

    Sunday, April 02, 2017 2:09 PM
  • Darren,

    I think I understand and one thing that I've thought about it is "how do I save these things"?

    If it's just one run, then setting up an event and have the results in the eventargs works, but not if it runs, runs again after a while, and so on. I'm not there yet but I think maybe store the results to file (binary or even XML) which would then free things up. It'll automatically save them.

    *****

    This is the latest build:

    http://www.fls-online.net/VBNet_Forum/04-02-17/Test_ServerConnectivityTesting.zip

    Run it with what I have and you'll "hear" what it's doing. No, I won't leave that annoying beep in it (besides, you'll think that your phone is ringing), but you'll get a sense of what it's doing.

    Once it's done, at the end of it you'll see something like this:

    Before you change them to yours, uncomment out the fake IP and run it again. What you'll hear with the beep will change.

    That will also give you an indication of what's going on (and the answer is "because it's timing out and by that time, the real IP's minimum lapsed has expired").

    Finally then, try it with your real ones. I'll wait to hear back from you before I proceed.

    So you'll know, I'll be out most of tomorrow.


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Sunday, April 02, 2017 2:18 PM
  • Yes saving it to XML/binary makes sense

    Okay have run it as is without and changes and results I see are same as your screenshot as below - just the two different statuses

    Ran it with fake IP uncommented and yes I can hear difference in the beep

    Finally ran it with my IP's - beep different again and again just seeing the two different statuses (Success or TimedOut)

    That's fine, I am actually booked solid tomorrow myself so not back until later in day anyway :)


    Darren Rose

    Sunday, April 02, 2017 2:39 PM
  • Yes saving it to XML/binary makes sense

    Okay have run it as is without and changes and results I see are same as your screenshot as below - just the two different statuses

    Ran it with fake IP uncommented and yes I can hear difference in the beep

    Finally ran it with my IP's - beep different again and again just seeing the two different statuses (Success or TimedOut)

    That's fine, I am actually booked solid tomorrow myself so not back until later in day anyway :)


    Darren Rose


    Do you still want to save the individual test results or just the aggregate information?

    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Sunday, April 02, 2017 3:14 PM
  • Do you still want to save the individual test results or just the aggregate information?


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    If it is possible to have an option to save all the test results I suppose it may be useful in some cases, but only as an option if it is not going to cause a problem or a lot of work for you - the main bit is the aggregate information

    Darren Rose

    Sunday, April 02, 2017 3:22 PM
  • Darren,

    I'll see what I can come up with then.


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Sunday, April 02, 2017 3:26 PM

  • If it is possible to have an option to save all the test results I suppose it may be useful in some cases, but only as an option if it is not going to cause a problem or a lot of work for you - the main bit is the aggregate information

    Darren Rose

    I'll re-visit this later if it's shown that you need them.

    The problem is that the raw test data is currently in instances of a private class. I can't publicly expose them unless the class is public too (or I create another public class which is pointless).

    Are you ok with that?


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Sunday, April 02, 2017 3:54 PM
  • I'll re-visit this later if it's shown that you need them.

    The problem is that the raw test data is currently in instances of a private class. I can't publicly expose them unless the class is public too (or I create another public class which is pointless).

    Are you ok with that?


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Okay that's fine with me- if I did need them then would only need it all just dumped to a csv file or similar rather than having access directly to each element of it

    Darren Rose

    Sunday, April 02, 2017 3:58 PM

  • Okay that's fine with me- if I did need them then would only need it all just dumped to a csv file or similar rather than having access directly to each element of it

    Darren Rose

    That makes me think about how to keep all of this stuff together. It might be that one of the parameters will be a directory path - everything goes into that directory (but I don't yet know what "everything" is!).

    I'll get it to where I was going to then sit back and think about the bigger picture. ;-)


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Sunday, April 02, 2017 4:07 PM

  • Okay that's fine with me- if I did need them then would only need it all just dumped to a csv file or similar rather than having access directly to each element of it

    Darren Rose

    That makes me think about how to keep all of this stuff together. It might be that one of the parameters will be a directory path - everything goes into that directory (but I don't yet know what "everything" is!).

    I'll get it to where I was going to then sit back and think about the bigger picture. ;-)


    "A problem well stated is a problem half solved.” - Charles F. Kettering


    Okay no problem - will make more sense as it develops I suspect :)

    Darren Rose

    Sunday, April 02, 2017 4:09 PM
  • Darren,

    I won't have time to work on it today but I was thinking: I think I've been seeing this from the wrong perspective. The data that's in the private class is what needs to be persisted and, from that, it will have a method that will generate the aggregate "output".

    I think. ;-)


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Monday, April 03, 2017 1:35 PM
  • Darren,

    I won't have time to work on it today but I was thinking: I think I've been seeing this from the wrong perspective. The data that's in the private class is what needs to be persisted and, from that, it will have a method that will generate the aggregate "output".

    I think. ;-)


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Okay that's fine

    I can see that logic


    Darren Rose

    Monday, April 03, 2017 1:38 PM

  • Okay that's fine

    I can see that logic


    Darren Rose

    Darren,

    I've copied the project directory to a safe place so that I can get back to where I am if my idea proves to be flawed. It'll take a while to even know (plus a have a job too), so don't think that I'm ignoring this.


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Tuesday, April 04, 2017 12:18 PM

  • Okay that's fine

    I can see that logic


    Darren Rose

    Darren,

    I've copied the project directory to a safe place so that I can get back to where I am if my idea proves to be flawed. It'll take a while to even know (plus a have a job too), so don't think that I'm ignoring this.


    "A problem well stated is a problem half solved.” - Charles F. Kettering


    That's fine - no hurry at all

    Darren Rose

    Tuesday, April 04, 2017 12:19 PM


  • That's fine - no hurry at all

    Darren Rose

    Like I said the other day, this is the time of the year when I get a bunch of work-related stuff.

    I've got a directive of "We need this and that and ..." ending with "...by tomorrow morning, today would be better. Is that possible?"

    <blink>

    Anyway, I'll be back later in the week, but just to let you know what's going on.


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Tuesday, April 04, 2017 2:50 PM
  • Don't you just love "last minute" clients - "I need this done yesterday etc"

    No problem - completely understand


    Darren Rose

    Tuesday, April 04, 2017 3:19 PM
  • Don't you just love "last minute" clients - "I need this done yesterday etc"

    No problem - completely understand


    Darren Rose


    Darren,

    When it rains it pours – I have a lot going on with several projects ‘all at the same time’, so I’ll be days before I’m able to get back to this in earnest.

    I’m at a stopping point for now and wanted to run this by you.

    *****

    Note: The following screenshots are from yesterday, so don’t let the dates confuse you.

    I wanted to explain my thoughts about the process here.

    I have a class set up specifically to keep up with the raw test data (what you saw the other day when I sent the project directory to you). I think that with that, I can then have it “create final output” because it will have all of the raw data to create it from.

    I then continued that thought and I’ve put an instance of this newest class into the first thing I did last week: The configuration class. That is to say that they’re now combined as shown here.

    Once the test routine has been run, what you’ll see might be confusing and it also has redundant data as shown here. The repeated information is intentional.

    Note in the last screenshot that there are two different date/times per instance.

    ”Server Test Routine Date/Time” is the group and “Test Date/Time” is the actual date/time of the raw test. By grouping it on Server Test Routine, you can keep these running forever if you want. I’ll have to lose the XML and go with binary, but that’s the concept.

    So you create a “test” the way we’ve been doing – use the other class to run it and at the end of that run, I’ll then have it save the test results – or I should say, I’ll have it update what’s been saved or create it if it doesn’t exist.

    When needed, this new class can then generate the output from one server test run or from multiple ones, spanned.

    It’s all concept but tell me what you think please?

     


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Wednesday, April 05, 2017 3:07 PM
  • Hi Frank

    Firstly no problem at all - work has to come first and to be honest quite busy this end as well so no worries

    As for the concept - yes I can understand the logic and it definitely makes sense and sounds like a good plan


    Darren Rose

    Wednesday, April 05, 2017 3:29 PM
  • Hi Frank

    Firstly no problem at all - work has to come first and to be honest quite busy this end as well so no worries

    As for the concept - yes I can understand the logic and it definitely makes sense and sounds like a good plan


    Darren Rose

    When I can get back to this I'm going to take it further and test what I can.

    I can see where the historical [raw] data might come in handy for analysis, even if you later want to change what and how it creates the final part.

    We'll see. ;-)


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Wednesday, April 05, 2017 3:34 PM
  • Hi Frank

    Firstly no problem at all - work has to come first and to be honest quite busy this end as well so no worries

    As for the concept - yes I can understand the logic and it definitely makes sense and sounds like a good plan


    Darren Rose

    Darren,

    I'm trying to get my head back into this.

    What do you suppose would be the longest amount of time that you'd want to run a test? 24 hours or is it possible that it might be "until I tell it to stop"?


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Friday, April 07, 2017 6:47 PM
  • Darren,

    I'm trying to get my head back into this.

    What do you suppose would be the longest amount of time that you'd want to run a test? 24 hours or is it possible that it might be "until I tell it to stop"?

    Hi,

    With the fact we can change the interval between pings so it does it say every 60 minutes or even more than that I suppose there is the option to have it running for a few days perhaps - maybe 7? but I cannot see a reason for ever doing it any more than that to be honest


    Darren Rose

    Friday, April 07, 2017 6:51 PM

  • Hi,

    With the fact we can change the interval between pings so it does it say every 60 minutes or even more than that I suppose there is the option to have it running for a few days perhaps - maybe 7? but I cannot see a reason for ever doing it any more than that to be honest


    Darren Rose

    I'm trying to figure out how to consolidate it all and I'll work on it more this weekend.

    I'm focused on saving the "raw test results" and not so much concerned [yet] about what to do with that information.

    I'll figure it out then I suppose. ;-)

    I'll get back to this over the weekend and report back then.


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Friday, April 07, 2017 6:56 PM
  • I'll get back to this over the weekend and report back then.

    Okay thank you Frank :)

    Darren Rose

    Friday, April 07, 2017 7:07 PM
  • I'll get back to this over the weekend and report back then.

    Okay thank you Frank :)

    Darren Rose

    I keep thinking about various "what if" things and I'm trying to work through those rather than waiting for it to crop up in the final form.

    I'll have more when I can, hopefully Sunday.


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Saturday, April 08, 2017 8:42 PM
  • Okay thanks Frank

    Darren Rose

    Saturday, April 08, 2017 8:49 PM
  • Okay thanks Frank

    Darren Rose

    Darren,

    This probably won't seem like much progress, but this is a slow process and I'm pushed for time these days.

    Here's the latest build:

    http://www.fls-online.net/VBNet_Forum/04-09-17/Test_ServerConnectivityTesting.zip

    I'm sure you recall that the last time I sent it to you (which I think was a week ago today), it was mostly still about the setttings. How about change what I have to yours and in the form's .Load, you'll see this:

    Uncomment out the "SaveToBinary" and "Stop", then run it to that point. Change the path and file name to whatever you want but it's saving your settings to a binary file - but more than that, you'll need that file for next part that does the actual testing.

    Here's my thinking: Since the next part will need to know where to save the raw test data once done (currently it's still just running one time), then my reasoning is to give it that binary file and since it will then have everything needed, it'll run the tests based on what's in that file and at the end, update the internal data to include the newest set of tests.

    Once you've saved the file, comment those back out and run it:

    The count of server test routines should increase by one. To get an idea of what I have in mind for how to get the data while it's running (for the longer runs), try that a few times, then stop the program and uncomment out these lines:

    My theory is that I can create a clone of the data and you can then freely use it (read-only) to then create the aggregate test results. I've not even started that part, but it's all based on having the raw test data.

    Note this also: When it's running, it's actually updating a temporary file in a temporary directory that's created. At the end of things, it deletes your original file, moves the temp file to your original location, and deletes the temporary file and directory.

    If something happens midway through, that last part won't happen and you'll see a message box showing you where that file is. Delete the directory and go on with it - but I have it there for now so that you won't be surprised.

    *****

    I'll be in and out today, including a few hours of downtime for this computer. Every few months I use a hard drive duplicator and I clone the data to another hard drive (then put that one back on the shelf).

    That way if something catastrophic happens, I can be at least "a few months old" within a few minutes and with my online backups, hopefully have everything up to date by the end of the day.

    Been there done that, so I've learned the hard way. ;-)


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Sunday, April 09, 2017 2:10 PM
  • Hi Frank

    Okay have run it a 6 times following you instructions and it works as described, I then uncommented code and ran it one more time to see the results stored in clone - all works okay

    Looking really good so far :)

    **

    Yes I know that feeling too - also been caught out in past so data now backed up in multiple places religiously so I don't lose anything again


    Darren Rose

    Sunday, April 09, 2017 2:36 PM
  • Hi Frank

    Okay have run it a 6 times following you instructions and it works as described, I then uncommented code and ran it one more time to see the results stored in clone - all works okay

    Looking really good so far :)

    **

    Yes I know that feeling too - also been caught out in past so data now backed up in multiple places religiously so I don't lose anything again


    Darren Rose

    Sorry that it took so long to get back.

    Depending on work, I'll continue with it tomorrow.


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Sunday, April 09, 2017 9:14 PM
  • Hi Frank

    Okay have run it a 6 times following you instructions and it works as described, I then uncommented code and ran it one more time to see the results stored in clone - all works okay

    Looking really good so far :)

    **

    Yes I know that feeling too - also been caught out in past so data now backed up in multiple places religiously so I don't lose anything again


    Darren Rose

    Darren,

    I have some test code (in the form's code for now - so I can figure out the next step) and per Ping Reply Test, I need to put a class together that will do all of the following.

    I want to ask you about this first of them:

    For this, I'm going back to what you said you wanted a few weeks ago:

    "...name, IP address, status (up/down), average roundtrip, max roundtrip, min roundtrip..."

    We later embellished the round-trip information to include the actual test date/time and that's what you see there. Those are currently from a private class:

        Private Class RoundTripData
            Public Property TripMilliseconds As Double
            Public Property TripDateTime As Nullable(Of DateTime)
        End Class

    It won't stay like that - this is for testing - but you see that the DateTime is a Nullable. I did that because "average" doesn't have a DateTime to associate it with.

    Is this what you want or should I do it differently?

    Also, for name - the first thing you see in the MessageBox - what should that be?


    "A problem well stated is a problem half solved.” - Charles F. Kettering


    • Edited by Frank L. Smith Monday, April 10, 2017 4:55 PM ...misworded
    Monday, April 10, 2017 4:54 PM
  • Hi Frank

    Yes the returned data seems exactly what I need

    For name I would either have the hostname if a) we asked it to get one and b) it found one - or the alias if not perhaps?


    Darren Rose

    Monday, April 10, 2017 5:00 PM
  • Hi Frank

    Yes the returned data seems exactly what I need

    For name I would either have the hostname if a) we asked it to get one and b) it found one - or the alias if not perhaps?


    Darren Rose

    So maybe like this then?

    Hostname if it's not the default. If it is:
        Aliasname if it's not the default. If it is:
            IP_String

    How about that?


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Monday, April 10, 2017 5:02 PM
  • yes that sounds ideal

    Darren Rose

    Monday, April 10, 2017 5:32 PM
  • Darren,

    Ok, with that, this is what I have so far (again though, this is temporary, just for testing):

    Your thoughts?


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Monday, April 10, 2017 6:31 PM
  • That looks very good Frank - exactly the information I would need to show in a list or whatever control I decide upon

    Only comment I would have at this stage is perhaps don't even need to show Round-trip Test Date/Time for Average as we know it is not relevant and will be null


    Darren Rose

    Monday, April 10, 2017 6:52 PM
  • That looks very good Frank - exactly the information I would need to show in a list or whatever control I decide upon

    Only comment I would have at this stage is perhaps don't even need to show Round-trip Test Date/Time for Average as we know it is not relevant and will be null


    Darren Rose

    Right - this was just an experiment to see what to get and how to get it.

    I'll be better armed now when I get to the real deal of putting it together more cohesively later this week.


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Monday, April 10, 2017 6:57 PM
  • fantastic - thanks Frank

    Darren Rose

    Monday, April 10, 2017 6:58 PM
  • fantastic - thanks Frank

    Darren Rose

    Darren,

    I keep trying to get to this. Several times yesterday and today I'd get my head back into the "oh right, I remember now" - and I'd get an e-mail and have to take off to work through that.

    I'll continue it eventually though.


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Wednesday, April 12, 2017 4:20 PM
  • No problem at all Frank - appreciate your busy with work

    Darren Rose

    Wednesday, April 12, 2017 4:24 PM
  • No problem at all Frank - appreciate your busy with work

    Darren Rose

    At least to catch you up on where I am, I have a method that will return all of the server test DateTimes. The terms are difficult to keep up with here, but I don't mean the individual test times of each "ping", I mean the DateTime of that run of them.

    By the way, I have them all rounded to to the nearest minute; the seconds will show zero for all of them (intentionally).

    I have added a new function (named "GetRawTestResults") that will get all of the individual test runs from the specified server ping test date and summarize that data then return an array of the summary info.

    For each (8 in my case), the instance members look like this:

    The "DisplayName" is what we talked about the other day with Hostname (if not the default), or Aliasname (if not the default) or IP as a string.

    RoundTripStats is a small class that looks like this:

    Lastly, TestResultStatus is an array of IPStatus - whatever was returned.

    The string version will show whatever was returned as comma-separated string.

    What are your thoughts on this so far?


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Wednesday, April 12, 2017 5:24 PM
  • That all sounds absolutely brilliant so far Frank - thank you :)

    Darren Rose

    Wednesday, April 12, 2017 5:34 PM
  • That all sounds absolutely brilliant so far Frank - thank you :)

    Darren Rose


    Ok, more when I can get back to it.

    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Wednesday, April 12, 2017 5:37 PM
  • Darren,

    This is latest build which I've added to this morning:

    http://www.fls-online.net/VBNet_Forum/04-13-17/Test_ServerConnectivityTesting.zip

    This is what I now have: Once you run it like you did last time, another form will display modally:

    The combo has the server test times and since the date in this has thoroughly confused me, I'm referring to those as Ping Reply Tests. With mine, I have a lot of them but choose whatever you have:

    When you select one, the DataGridView will display the results - that is the aggregate results, not the individual tests:

    I chose this particular one because in testing, I noticed that status for the test using Wikipedia had a mixture as you see above. That then led me to adding another method and to demonstrate it, right-click on that row:

    It will prompt you to select a place to put the text file and when you select one, it will then write out the data:

    http://www.fls-online.net/VBNet_Forum/04-13-17/RawTestResults.txt

    Let me know what you think and I'll get back to it when I can.


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Thursday, April 13, 2017 4:38 PM
  • Hi Frank

    Initial opinion and testing it is looking good - just need to run it several times over next few hours to get a series of results to look at

    One comment for now is might need to rethink the name/alias thing - as if I include www.google.co.uk then the hostname it shows for it is lhr25s09-in-f3.1e100.net which is no use for anyone glancing to know what it is - so either need to show both name and alias under name or perhaps have a separate column/variable to hold alias or at least some way to show a recognizable name for it

    Perhaps it would be easier to separate them some how depending on if a IP address or a website address e.g. "Name" column shows hostname if retrieved or friendly name, and another column to show IP address

    Maybe for websites we don't need to look up hostname as we are supplying the name we know so can skip getting hostname for websites and just show the name we chose e.g. for above www.google.co.uk

    Sorry hope that make sense, typing whilst on phone to customer!


    Darren Rose

    Thursday, April 13, 2017 5:04 PM
  • Hi Frank

    Initial opinion and testing it is looking good - just need to run it several times over next few hours to get a series of results to look at

    One comment for now is might need to rethink the name/alias thing - as if I include www.google.co.uk then the hostname it shows for it is lhr25s09-in-f3.1e100.net which is no use for anyone glancing to know what it is - so either need to show both name and alias under name or perhaps have a separate column/variable to hold alias or at least some way to show a recognizable name for it

    Perhaps it would be easier to separate them some how depending on if a IP address or a website address e.g. "Name" column shows hostname if retrieved or friendly name, and another column to show IP address

    Maybe for websites we don't need to look up hostname as we are supplying the name we know so can skip getting hostname for websites and just show the name we chose e.g. for above www.google.co.uk

    Sorry hope that make sense, typing whilst on phone to customer!


    Darren Rose


    I think you mean to rethink the DisplayName - or more specifically, how to formulate it?

    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Thursday, April 13, 2017 5:09 PM
  • Darren,

    One thing that I'd like to get you to think about is this:

    If you look at row 3 (the one that has two statuses showing), notice that the minimum is 0. No surprise there because it timed out so of course the lowest is 0.

    I can remove those in the calculations - but would it be confusing?


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Thursday, April 13, 2017 5:13 PM