user2085339
user2085339

Reputation: 155

unrepeatable Random Number in VB.net

I want to generate 200,000 random IP addresses without repeating the same IP address for example:

(1-254).(1-254).(1-254).1-254)

in vb.net my code is :

        While c < 200001
        IP = random.Next(1, 254).ToString + "." + random.Next(1, 254).ToString + "." +           random.Next(1, 254).ToString + "." + random.Next(1, 254).ToString
        On Error Resume Next
        IPHost = Dns.GetHostEntry(IP.ToString)
        domain = IPHost.HostName.ToString()
        objWriter.Write(IP)
        objWriter.Write("   ")
        objWriter.WriteLine(domain)
        TextBox1.Text = IP
        Application.DoEvents()

    End While
    objWriter.Close()
    MsgBox("DONE")

regards

Upvotes: 1

Views: 355

Answers (2)

sloth
sloth

Reputation: 101162

Since a IP4 address consists of 4 bytes, you can simply use Random.NextBytes with a size 4 array to create one.

To prevent creating duplicate addresses, simply use a HashSet and a while loop.

To filter out reserved addresses, you can just use the code used in this answer (some reserved addresses would be easy to check, e.g. multicast addresses all start with 1110, but no need to reinvent the wheel here). I converted it to VB.Net below

So your code could look like this:

Dim r = New Random()

Dim addresses = New HashSet(Of String)()

While addresses.Count < 200000
    Dim buffer As Byte() = New Byte(3) {}
    r.NextBytes(buffer)
    Dim address = String.Join(".", buffer)
    If Not IsNonRoutableIpAddress(address) Then
        addresses.Add(address)
    End If
End While

and the converted code for IsNonRouteableIpAddress:

Public Shared Function IsNonRoutableIpAddress(ipAddress__1 As String) As Boolean
    'Reference: http://en.wikipedia.org/wiki/Reserved_IP_addresses

    'if the ip address string is empty or null string, we consider it to be non-routable
    If [String].IsNullOrEmpty(ipAddress__1) Then
        Return True
    End If

    'if we cannot parse the Ipaddress, then we consider it non-routable
    Dim tempIpAddress As IPAddress = Nothing
    If Not IPAddress.TryParse(ipAddress__1, tempIpAddress) Then
        Return True
    End If

    Dim ipAddressBytes As Byte() = tempIpAddress.GetAddressBytes()

    'if ipAddress is IPv4
    If tempIpAddress.AddressFamily = System.Net.Sockets.AddressFamily.InterNetwork Then
        If IsIpAddressInRange(ipAddressBytes, "10.0.0.0/8") Then
            'Class A Private network check
            Return True
        ElseIf IsIpAddressInRange(ipAddressBytes, "172.16.0.0/12") Then
            'Class B private network check
            Return True
        ElseIf IsIpAddressInRange(ipAddressBytes, "192.168.0.0/16") Then
            'Class C private network check
            Return True
        ElseIf IsIpAddressInRange(ipAddressBytes, "127.0.0.0/8") Then
            'Loopback
            Return True
        ElseIf IsIpAddressInRange(ipAddressBytes, "0.0.0.0/8") Then
            'reserved for broadcast messages
            Return True
        End If

        'its routable if its ipv4 and meets none of the criteria
        Return False
    'if ipAddress is IPv6
    ElseIf tempIpAddress.AddressFamily = System.Net.Sockets.AddressFamily.InterNetworkV6 Then
        'incomplete
        If IsIpAddressInRange(ipAddressBytes, "::/128") Then
            'Unspecified address
            Return True
        ElseIf IsIpAddressInRange(ipAddressBytes, "::1/128") Then
            'lookback address for localhost
            Return True
        ElseIf IsIpAddressInRange(ipAddressBytes, "2001:db8::/32") Then
            'Addresses used in documentation
            Return True
        End If

        Return False
    Else
        'we default to non-routable if its not Ipv4 or Ipv6
        Return True
    End If
End Function

''' <summary>
''' 
''' </summary>
''' <param name="ipAddressBytes"></param>
''' <param name="reservedIpAddress"></param>
''' <returns></returns>
Private Shared Function IsIpAddressInRange(ipAddressBytes As Byte(), reservedIpAddress As String) As Boolean
    If [String].IsNullOrEmpty(reservedIpAddress) Then
        Return False
    End If

    If ipAddressBytes Is Nothing Then
        Return False
    End If

    'Split the reserved ip address into a bitmask and ip address
    Dim ipAddressSplit As String() = reservedIpAddress.Split(New Char() {"/"C}, StringSplitOptions.RemoveEmptyEntries)
    If ipAddressSplit.Length <> 2 Then
        Return False
    End If

    Dim ipAddressRange As String = ipAddressSplit(0)

    Dim ipAddress__1 As IPAddress = Nothing
    If Not IPAddress.TryParse(ipAddressRange, ipAddress__1) Then
        Return False
    End If

    ' Convert the IP address to bytes.
    Dim ipBytes As Byte() = ipAddress__1.GetAddressBytes()

    'parse the bits
    Dim bits As Integer = 0
    If Not Integer.TryParse(ipAddressSplit(1), bits) Then
        bits = 0
    End If

    ' BitConverter gives bytes in opposite order to GetAddressBytes().
    Dim maskBytes As Byte() = Nothing
    If ipAddress__1.AddressFamily = AddressFamily.InterNetwork Then
        Dim mask As UInteger = Not (UInteger.MaxValue >> bits)
        maskBytes = BitConverter.GetBytes(mask).Reverse().ToArray()
    ElseIf ipAddress__1.AddressFamily = AddressFamily.InterNetworkV6 Then
        '128 places
        Dim bitArray As New BitArray(128, False)

        'shift <bits> times to the right
        ShiftRight(bitArray, bits, True)

        'turn into byte array
        maskBytes = ConvertToByteArray(bitArray).Reverse().ToArray()
    End If


    Dim result As Boolean = True

    'Calculate
    For i As Integer = 0 To ipBytes.Length - 1

        result = result And CByte(ipAddressBytes(i) And maskBytes(i)) = ipBytes(i)
    Next

    Return result
End Function

''' <summary>
''' 
''' </summary>
''' <param name="bitArray"></param>
''' <param name="shiftN"></param>
''' <param name="fillValue"></param>
Private Shared Sub ShiftRight(bitArray As BitArray, shiftN As Integer, fillValue As Boolean)
    For i As Integer = shiftN To bitArray.Count - 1
        bitArray(i - shiftN) = bitArray(i)
    Next

    'fill the shifted bits as false
    For index As Integer = bitArray.Count - shiftN To bitArray.Count - 1
        bitArray(index) = fillValue
    Next
End Sub

''' <summary>
''' 
''' </summary>
''' <param name="bitArray"></param>
''' <returns></returns>
Private Shared Function ConvertToByteArray(bitArray As BitArray) As Byte()
    ' pack (in this case, using the first bool as the lsb - if you want
    ' the first bool as the msb, reverse things ;-p)
    Dim bytes As Integer = (bitArray.Length + 7) / 8
    Dim arr2 As Byte() = New Byte(bytes - 1) {}
    Dim bitIndex As Integer = 0
    Dim byteIndex As Integer = 0

    For i As Integer = 0 To bitArray.Length - 1
        If bitArray(i) Then
            arr2(byteIndex) = arr2(byteIndex) Or CByte(1 << bitIndex)
        End If

        bitIndex += 1
        If bitIndex = 8 Then
            bitIndex = 0
            byteIndex += 1
        End If
    Next

    Return arr2
End Function

Upvotes: 2

Psychemaster
Psychemaster

Reputation: 876

Stepping around issues such as reserved IP blocks, you could simply write generated IPs to a Collection and then invoke the collection's Contains() method to check if the generated IP exists in the collection.

As @Heinzi pointed out, a HashSet would also be an option - perhaps a better one since you're writing 200,000 entries to it.

Upvotes: 3

Related Questions