【VB.NET】利用纯真IP数据库查询IP地址及信息

几年前从某个博客抄来的,已经忘记原地址了,如果需要C#版的,可以在博客园搜到吧。
我因为自己用,所以转换为了VBNET代码,而且也放置了很久,今天无意间翻出来,就分享给大家吧。

首先,先下载 纯真数据库,名称应该是 QQWry.dat 。
之后将数据库文件复制到程序的主目录即可。

Imports System.IO
Imports System.Text
Imports System.Text.RegularExpressions
Imports System.Net
Imports System.Net.Sockets

‘‘‘ <summary>IP地址查询</summary>
Public NotInheritable Class IPQuery

    ‘‘‘ <summary>IP地址描述</summary>
    Public Structure IPLocation
        Sub New(ByVal i As String, ByVal c As String, ByVal l As String)
            IP = i
            Country = c
            Local = l
        End Sub
        ‘‘‘ <summary>IP地址</summary>
        Dim IP As String
        ‘‘‘ <summary>地域\国家\机构</summary>
        Dim Country As String
        ‘‘‘ <summary>地域描述</summary>
        Dim Local As String

        ‘‘‘ <summary>返回完整名称</summary>
        Overloads Function ToString() As String
            Return Me.Country & Me.Local
        End Function
        ‘‘‘ <param name="ls">连接字符</param>
        Overloads Function ToString(ByVal ls As String) As String
            Return Me.Country & ls & Me.Local
        End Function

        ‘ 强制转换
        Public Shared Widening Operator CType(ByVal o As IPLocation) As String
            Return o.ToString
        End Operator

    End Structure

    Shared encoding As Encoding = encoding.GetEncoding("GB2312")

    Shared ipCount As Integer
    Shared fsinoffiset As Integer
    Shared lsinoffiset As Integer
    Shared data As Byte()
    ‘ 加强线程访问安全
    Shared rwl As New Threading.ReaderWriterLock

    ‘‘‘ <summary>刷新IP数据库</summary>
    Shared Sub ReIPData(ByVal dataPath As String)
        rwl.AcquireWriterLock(-1) ‘设置写权限,禁止读权限

        ‘ 尝试回收内存中的数据库
        If data IsNot Nothing Then
            data = Nothing
            GC.Collect()
        End If
        ‘ 读取数据
        data = IO.File.ReadAllBytes(dataPath)
        fsinoffiset = CInt(data(0)) + (CInt(data(1)) << 8) + (CInt(data(2)) << 16) + (CInt(data(3)) << 24)
        lsinoffiset = CInt(data(4)) + (CInt(data(5)) << 8) + (CInt(data(6)) << 16) + (CInt(data(7)) << 24)
        ipCount = (lsinoffiset - fsinoffiset) / 7 + 1

        rwl.ReleaseWriterLock()

        If ipCount <= 1 Then Throw New ApplicationException("提供的IP数据错误!")
    End Sub

    Shared Sub New()
        ‘ TODO 替换为自己的数据库地址
        ReIPData(Application.StartupPath & "\QQWry.dat")
    End Sub

    ‘‘‘ <summary>返回数据库中IP纪录总数</summary>
    Shared ReadOnly Property Count() As Integer
        Get
            Return ipCount
        End Get
    End Property

    ‘‘‘ <summary>查询一组IP地址</summary>
    Shared Function QueryAll(ByVal ParamArray ips As String()) As IPLocation()
        If ips Is Nothing OrElse ips.Length = 0 Then Return Nothing

        Dim ipls(ips.Length - 1) As IPLocation
        For i As Integer = 0 To ips.Length - 1
            ipls(i) = Query(ips(i))
        Next
        Return ipls
    End Function

    ‘‘‘ <summary>查询IP地址</summary>
    Shared Function Query(ByVal ip As String) As IPLocation

        rwl.AcquireReaderLock(-1) ‘设置读权限

        Dim ads As IPAddress = IPAddress.Parse(ip)
        If ads.AddressFamily <> AddressFamily.InterNetwork Then Throw New ArgumentException("不支持非IPV4协议")
        If IPAddress.IsLoopback(ads) Then
            rwl.ReleaseReaderLock()
            Return New IPLocation(ip, "本机或保留地址", "")
        End If

        ‘Dim intIp As UInteger = CUInt(IPAddress.HostToNetworkOrder(CInt(ads.Address)))
        Dim intIp As UInteger = m_ip2uint(ads.ToString)

        Dim iplon As IPLocation : iplon.IP = ip

        Dim right As UInteger = ipCount
        Dim left, middle, startIp, endIpOff, endIp As UInteger
        Dim countryFlag As Integer = 0

        While left < (right - 1)
            middle = (right + left) / 2
            startIp = GetStartIp(middle, endIpOff)
            If intIp = startIp Then
                left = middle
                Exit While
            End If
            If intIp > startIp Then
                left = middle
            Else
                right = middle
            End If
        End While

        startIp = GetStartIp(left, endIpOff)
        endIp = GetEndIp(endIpOff, countryFlag)
        If startIp <= intIp And endIp >= intIp Then
            Dim local As String = ""
            iplon.Country = GetCountry(endIpOff, countryFlag, local)
            If local = " CZ88.NET" Then local = "" ‘优化 用于去除部分IP地址返回的广告数据
            iplon.Local = local
        Else
            iplon.Country = "未知地区"
            iplon.Local = "" ‘"火星网友"
        End If

        rwl.ReleaseReaderLock()

        Return iplon
    End Function

    Private Shared Function GetStartIp(ByVal left As UInteger, ByRef endIpOff As UInteger) As UInteger
        Dim leftOffset As Integer = CInt(fsinoffiset + (left * 7))
        endIpOff = CUInt(data(leftOffset + 4)) + (CUInt(data(leftOffset + 5)) << 8) + (CUInt(data(leftOffset + 6)) << 16)
        Return CUInt(data(leftOffset)) + (CUInt(data(leftOffset + 1)) << 8) + (CUInt(data(leftOffset + 2)) << 16) + (CUInt(data(leftOffset + 3)) << 24)
    End Function
    Private Shared Function GetEndIp(ByVal endIpOff As UInteger, ByRef countryFlag As Integer) As UInteger
        countryFlag = data(endIpOff + 4)
        Return CUInt(data(endIpOff)) + (CUInt(data(endIpOff + 1)) << 8) + (CUInt(data(endIpOff + 2)) << 16) + (CUInt(data(endIpOff + 3)) << 24)
    End Function

    Private Shared Function GetCountry(ByVal endIpOff As UInteger, ByVal countryFlag As Integer, ByRef local As String) As String
        Dim country As String = ""
        Dim offset As UInteger = endIpOff + 4
        Select Case countryFlag
            Case 1, 2
                country = GetFlagStr(offset, countryFlag, endIpOff)
                offset = endIpOff + 8
                local = IIf(countryFlag = 1, "", GetFlagStr(offset, countryFlag, endIpOff))
            Case Else
                country = GetFlagStr(offset, countryFlag, endIpOff)
                local = GetFlagStr(offset, countryFlag, endIpOff)
        End Select
        Return country
    End Function

    Private Shared Function GetFlagStr(ByRef offset As UInteger, ByRef countryFlag As Integer, ByRef endIpOff As UInteger) As String
        Dim flag As Integer = 0
        Do

            flag = data(offset)
            If flag <> 1 And flag <> 2 Then Exit Do
            If flag = 2 Then
                countryFlag = 2
                endIpOff = offset - 4
            End If
            offset = CUInt(data(offset + 1)) + (CUInt(data(offset + 2)) << 8) + (CUInt(data(offset + 3)) << 16)
        Loop
        If offset < 12 Then Return ""
        Return GetStr(offset)
    End Function

    Private Shared Function GetStr(ByRef offset As UInteger) As String
        Dim lowByte As Byte = 0, highByte As Byte = 0
        Dim sb As New StringBuilder(16)
        Do
            lowByte = data(offset) : offset += 1
            If lowByte = 0 Then Return sb.ToString
            If lowByte > &H7F Then
                highByte = data(offset) : offset += 1
                If highByte = 0 Then Return sb.ToString
                sb.Append(encoding.GetString(New Byte() {lowByte, highByte}))
            Else
                sb.Append(ChrW(lowByte))
            End If
        Loop
    End Function

    ‘‘‘ <summary>将ip地址转换为uint</summary>
    Private Shared Function m_ip2uint(ByVal ip As String) As UInteger
        Dim bs As Byte() = IPAddress.Parse(ip).GetAddressBytes
        Return CUInt(bs(3)) + (CUInt(bs(2)) << 8) + (CUInt(bs(1)) << 16) + (CUInt(bs(0)) << 24)
    End Function

End Class

如果你要设置自定义的数据库位置,记得修改 Shared Sub New 这个方法,或者干脆删除它,自己调用 ReIPData 来设置数据库的地址。

使用方法很简单,如下:

Dim iploca = IPQuery.Query("127.0.0.1")
Dim ipdesc = String.Format("IP {0} 的详细地址为: {1} - {2}", iploca.IP, iploca.Country, iploca.Local)
时间: 2024-08-25 09:11:30

【VB.NET】利用纯真IP数据库查询IP地址及信息的相关文章

php利用新浪接口查询ip获取地理位置示例

? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <?php function getIPLoc_sina($queryIP){   $url = 'http://int.dpool.sina.com.cn/iplookup/iplookup.php?format=json&ip='.$queryIP;   $ch = curl_init($url);    curl_setopt($ch,CURLOPT_ENCODING ,'utf8');

IP数据库 纯真版+IP

IP数据库 纯真版20140715.rar 百度下载:http://pan.baidu.com/s/1kTxEbQZ qqwry.dat QQWRY:http://pan.baidu.com/s/1qWughJI 官网下载:http://www.cz88.net/ IP数据库 纯真版+IP

python 利用淘宝IP库 查询IP归属地

#coding:utf-8 from django.test import TestCase import json import urllib ip = "114.114.114.114" url = "http://ip.taobao.com/service/getIpInfo.php?ip="+ ip #返回数据 jsondata = json.loads(urllib.urlopen(url).read()) print jsondata #省份 regio

web项目之BBS---从数据库查询动态生成版块信息问题分析和小结

前期学习了 html5.0   css3   javascript, jsp 页面也已经入门,老师通过BBS 的web项目来给我们讲述这些知识点在实际项目中的应用. 具体的注册.登陆都只是简单的业务层逻辑问题,不予说明.项目开始的第二天,老师布置了作业: 想清楚动态生成版块信息的流程,给的提示如下: 这是 board表的字段:boardid.name.和一个父版块id 用 map 来存入,map 的键就是父版块编号,值就是 List<Board>,这个 parentid 下面的所有Board

web项目--BBS之从数据库查询动态生成版块信息问题分析和小结

前期学习了 html5.0   css3   javascript, jsp 页面也已经入门,老师通过BBS 的web项目来给我们讲述这些知识点在实际项目中的应用. 具体的注册.登陆都只是简单的业务层逻辑问题,不予说明.项目开始的第二天,老师布置了作业: 想清楚动态生成版块信息的流程,给的提示如下: 这是 board表的字段:boardid.name.和一个父版块id 用 map 来存入,map 的键就是父版块编号,值就是 List<Board>,这个 parentid 下面的所有Board

【VB.NET】通过 IPIP.NET 数据库来查询IP地址

上一次介绍了利用纯真数据库查询IP地址详细信息的方法.然而纯真数据库是由网友反馈所提供的,很多数据描述并不准确,所以我上网找了一些其他的IP数据库,最后就找到了 ipip.net 这个网站所提供的IP数据库. IPIP所提供的数据库有付费和免费两个版本,我们可以直接使用其中的免费版本.下载地址 https://www.ipip.net/download.html (需要先注册一个帐号)压缩包内有一个PHP的解析类,还有一个 17monipdb.dat 文件就是数据库了,我们只需要用到它就可以了.

python查询ip归属地

本来想调用阿里的ip接口查询ip归属地.结果发现阿里的接口非常不给力,主要是不准确,不过是免费的且有地区和ISP的信息.以下是实现代码 # -*- coding: utf-8 -*- import requests def checkip(ip):     URL = 'http://ip.taobao.com/service/getIpInfo.php'     try:         r = requests.get(URL, params=ip, timeout=3)     excep

python学习-使用requests模块查询ip地址

思路是,使用requests模块调用阿里的ip接口查询ip归属地 关于requests模块的使用,可以查询相关文档,很强大,本次不做描述 #!/usr/bin/python #coding=utf-8 import requests   def checkip(ip):       URL = 'http://ip.taobao.com/service/getIpInfo.php'     try:         r = requests.get(URL, params=ip, timeout

[转]C#反射,根据反射将数据库查询数据和实体类绑定,并未实体类赋值

本文来自:http://www.cnblogs.com/mrchenzh/archive/2010/05/31/1747937.html /***************************************** * 说明:利用反射将数据库查询的内容自动绑定 *       到实体类 * * 时间:1:49 2009-9-19 * * 程序员:王文壮 * ***************************************/ /****************数据库脚本***