不多废话直接开始说一种超快的算法吧既然要极快莫过于o()的复杂度所以开辟一巨大的缓沖区用经典的空间换时间通过查表一步即可判定那如何定义表的大小还有key?先从cnctxt这个文件看起 这个文件是中国网通的路由表仔细观察下不难发现掩码位数最高不超过(即)事实上位的掩码是非常至少毕竟一个网通的网段里只划分了个ip已是相当的少了既然掩码位数最多只有所以ip的最后一位可以忽略不计而ip的前位共有^(=m)的组合所以将ip的前位作为keym的表长度正好定义出ip对应网段的表可以形象如下表示: / => table[] = true / => table[] = true table[] = true
table[] = true 检测的时候取ip前位检测表中对应是否为true即可判断出此ip的类型事实上本例中ip只有电信和网通两种状态(非网通网段都当作电信)因此只需bit即可保存每个记录这时表占用的内存只需m/=m下面就用asp教程来实现这功能 首先将路由表转化成一个m大小的缓存表考虑到asp的运行速度这里事先用c程序直接处理然后保存为一个m的二进制文件asp通过adbdostream读取数据流并缓存在appliction集合中所谓的数据流其实也就是个byte()变量可以通过midbascb这类二进制函数来处理 初始化函数: sub init() if lenb(application("cnc")) then exit sub end if with servercreateobject("adodbstream") type = open loadfromfile servermappath("cncdat") application("cnc") = read close end with end sub 通过appliction集合的缓存就不必每次都读取文件m大小的内存也是可以接受的接着就是分析ip地址将其前位转换成一个数字因为这里每个记录是按位(bit)保存的所以还要整除来对应到byte()的位置最后通过mod运算对应到具体字节的具体bit上听着有些复杂不过实现起来确是相当的简单: function ipiscnc(ip) dim arr val dim c arr = split(ip "") val = clng(arr()) * + clng(arr()) * + clng(arr()) c = ascb(midb(application("cnc") val + )) ipiscnc = _ (c and ^(val mod )) <> end function ipiscnc(ip)返回ip地址是否为网通 到此关键的两个函数就大功告成了接着测试: sub main() on error resume next init() if err then responsewrite "系统错误: " & errdescription exit sub end if dim ip ip = requestservervariables("remote_addr") if ipiscnc(ip) then responsewrite ip & "属于网通ip" else responsewrite ip & "属于电信ip" end if end sub main() 考虑到init函数需要文件的读取所以添加了错误捕捉不过通常情况下ipiscnc是不会错误的因为remote_addr返回的必然是个正确格式的ip 每当访问asp时除了第一次需加载文件外其余时候只需三四行代码既可以判定真正实现了空间换时间 |