Reinventing the framework is bad

There’s a bit of code on this site that regularly gets a few hits every day via search engines, namely my IP to country lookup code. BTW, WordPress is not so good at sharing code. There’s a function in that code that converts an IP string into a 64-bit integer (Int64). It does this by splitting an IP address into an array of four strings, then getting the hexadecimal value of those string, then joining the string back together and determining the numeric value. Sub-optimal, but it works.

It turns out that built into the .NET framework Net.IPAddress object, there are several methods that do this same thing but better. They are more robust, handle both IPv4 and IPv6 addresses, and the functions that are rewritten to use them run in about 1/3 the time (will post after the jump). My point is that before writing code, one should be familiar enough with the underlying framework to be sure that the same thing isn’t already written. One can get better code in less time.


Now for the code. First, please understand that the manner that .NET stores IP addresses internally is backwards from the way that the IP text database stores them. A typical IPv4 address only requires 4 bytes to store, yet an Int64 is 8 bytes. One must reverse the byte arrays to make sure that the IP/Int64 conversion goes according to plan.

Public Shared Function IPStringToLong(ByVal IPString As String) As Long
  Try
    Dim ip As Net.IPAddress = Net.IPAddress.Parse(IPString)
    Dim b() As Byte = ip.GetAddressBytes()

Array.Reverse(b)    'required by IP db format
    Select Case b.Length
      Case 4 To 7
        Return Convert.ToInt64(BitConverter.ToInt32(b, 0))
      Case 8 To 16
        Return BitConverter.ToInt64(b, 0)
      Case Else
        Return -1
    End Select
  Catch ex As Exception
    Return -1
  End Try
End Function

Public Shared Function IPLongToString(ByVal IPLong As Long) As String
  Try
    Dim b() As Byte = BitConverter.GetBytes(IPLong)
    Array.Reverse(b, 0, 4)

Dim i As Long = BitConverter.ToInt64(b, 0)
    Dim ip As New Net.IPAddress(i)
    Return ip.ToString
  Catch ex As Exception
    Return "0.0.0.0"
  End Try
End Function

Comments are closed.