Introduction
About a year ago I was looking for a way to get all active ip-addresses on subnet. It was a little part of the management LAN project.
Step 1. Calculating subnet
First of questions was how to "calculate" a network having just ip and mask values. This task was a good reason to optimize a huge amount of collected examples and manuals. That's what i finally got:
Dim mask() As Byte = IPAddress.Parse("255.255.255.0").GetAddressBytes
Dim iprev() As Byte = IPAddress.Parse("172.16.5.102").GetAddressBytes
Dim netid() As Byte = BitConverter.GetBytes(BitConverter.ToUInt32(iprev, 0) And BitConverter.ToUInt32(mask, 0))
Dim inv_mask() As Byte = mask.Select(Function(r) Not r).ToArray
Dim brCast() As Byte = BitConverter.GetBytes(BitConverter.ToUInt32(netid, 0) Xor BitConverter.ToUInt32(inv_mask, 0))
Step 2. Collecting
Let's fill our subnet with ip-addresses:
Private Sub fillIPs(ByVal ip1() As Byte, ByVal ip2() As Byte)
Dim tmpip As New Collection(Of ListViewItem)
For n As UInt32 = BitConverter.ToUInt32(ip1.Reverse.ToArray, 0) + 1 To BitConverter.ToUInt32(ip2.Reverse.ToArray, 0) - 1
tmpip.Add(New ListViewItem With {.Text = New Net.IPAddress(BitConverter.GetBytes(n).Reverse.ToArray).ToString,
.ImageIndex = 0})
Next
lv1.Items.Clear()
lv1.Items.AddRange(tmpip.ToArray)
End Sub
Step 3. Cleaning
Now remove inactive items using ping:
Private d As New Dictionary(of String, Ping)
Private Sub removeInactive(sender As Object, e As EventArgs) Handles Button2.Click
For Each item As ListViewItem In lv1.Items
Dim p As New Ping
d.Add(item.Text, p)
AddHandler p.PingCompleted, AddressOf p_pingCompleted
p.SendAsync(item.Text, 200, item.Text)
Next
End Sub
Private Sub p_pingCompleted(ByVal sender As Object, ByVal e As System.Net.NetworkInformation.PingCompletedEventArgs)
Dim server As String = e.UserState
Dim lvi As ListViewItem = lv1.FindItemWithText(server)
If e.Reply.Status = IPStatus.Success Then
lvi.ImageIndex = 1
Else
lvi.Remove()
End If
DirectCast(d(server), IDisposable).Dispose()
d.Remove(server)
End Sub
Note: Any EndPoints in subnet that are blocking ICMP-requests will be removed as inactive (This method works only for ip-addresses that can be pinged)
That's all.
Now we have very simple and very-very fast solution. Look again at image at the top of page. It was captured from sample project in real time. Great performance, isn't it? But it's just a project executed in IDE. Binary file will some faster of course.