VB.net中不可重复的随机数

时间:2014-08-28 08:40:10

标签: vb.net

我想生成200,000个随机IP地址而不重复相同的IP地址 例如:

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

在vb.net中 我的代码是:

        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")

问候

2 个答案:

答案 0 :(得分:3)

踩过保留IP块等问题,您可以简单地将生成的IP写入Collection,然后调用集合的Contains()方法来检查集合中是否存在生成的IP

正如@Heinzi指出的那样,HashSet也是一个选择 - 也许是一个更好的选择,因为你正在写200,000个条目。

答案 1 :(得分:2)

由于IP4地址由4个字节组成,因此您只需使用大小为4的数组Random.NextBytes即可创建一个。

要防止创建重复的地址,只需使用HashSetwhile循环。

要过滤掉保留地址,您只需使用this answer中使用的代码(一些保留地址很容易检查,例如多播地址都以1110开头,但不需要重新发明轮子)。我将它转换为VB.Net下面的

所以你的代码看起来像这样:

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

以及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