不多廢話直接開始說一種超快的算法吧既然要極快莫過於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時除了第一次需加載文件外其余時候只需三四行代碼既可以判定真正實現了空間換時間
From:http://tw.wingwit.com/Article/program/net/201311/14029.html