程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> ASP編程 >> 關於ASP編程 >> 判斷IP的來源是電信還是網通

判斷IP的來源是電信還是網通

編輯:關於ASP編程

      判斷ip的來源是電信還是網通,常用於站點的後台程序.典型的做法當然是查詢數據庫教程,數據庫裡保存著網通(或電信)的ip范圍,然後通過范圍搜索來決定該ip是否在網通(或電信)的區間內.不過每次都得查詢數據庫,效率顯然很低.

      不多廢話,直接開始說一種超快的算法吧.既然要極快,莫過於o(1)的復雜度,所以開辟一巨大的緩沖區,用經典的空間換時間,通過查表一步即可判定.那如何定義表的大小,還有key?先從cnc.txt這個文件看起.(http:///)

      這個文件是中國網通的路由表.仔細觀察下,不難發現掩碼位數最高不超過24(即255.255.255.0).事實上24位的掩碼是非常至少,畢竟一個網通的網段裡只劃分了256個ip,已是相當的少了.既然掩碼位數最多只有24,所以ip的最後一位可以忽略不計,而ip的前3位共有256^3(=16m)的組合.所以將ip的前3位作為key,16m的表長度,正好定義出ip對應網段的表.可以形象如下表示:

      123.0.0.0/24 => table[123.0.0] = true

      202.0.0.0/16 => table[202.0.0] = true

      table[202.0.1] = true

      ...

      table[202.0.255] = true

      檢測的時候取ip前3位,檢測表中對應是否為true即可判斷出此ip的類型.事實上,本例中ip只有電信和網通兩種狀態(非網通網段都當作電信),因此只需1bit即可保存每個記錄.這時表占用的內存只需16m/8=2m.下面就用asp教程來實現這功能.

      首先將路由表轉化成一個2m大小的緩存表.考慮到asp的運行速度,這裡事先用c程序直接處理,然後保存為一個2m的二進制文件.asp通過adbdo.stream讀取數據流,並緩存在appliction集合中.所謂的數據流其實也就是個byte()變量,可以通過midb,ascb這類二進制函數來處理.

      初始化函數:

      sub init()

      if lenb(application("cnc")) then

      exit sub

      end if

      with server.createobject("adodb.stream")

      .type = 1

      .open

      .loadfromfile server.mappath("cnc.dat")

      application("cnc") = .read

      .close

      end with

      end sub

      通過appliction集合的緩存,就不必每次都讀取文件.2m大小的內存也是可以接受的.接著就是分析ip地址,將其前3位轉換成一個數字,因為這裡每個記錄是按位(bit)保存的,所以還要整除8來對應到byte()的位置.最後通過mod運算對應到具體字節的具體bit上.聽著有些復雜,不過實現起來確是相當的簡單:

      function ipiscnc(ip)

      dim arr, val

      dim c

      arr = split(ip, ".")

      val = clng(arr(0)) * 65536 + clng(arr(1)) * 256 + clng(arr(2))

      c = ascb(midb(application("cnc"), val 8 + 1, 1))

      ipiscnc = _

      (c and 2^(val mod 8)) <> 0

      end function

      ipiscnc(ip),返回ip地址是否為網通.

      到此關鍵的兩個函數就大功告成了,接著測試:

      sub main()

      on error resume next

      init()

      if err then

      response.write "系統錯誤: " & err.description

      exit sub

      end if

      dim ip

      ip = request.servervariables("remote_addr")

      if ipiscnc(ip) then

      response.write ip & "屬於網通ip"

      else

      response.write ip & "屬於電信ip"

      end if

      end sub

      main()

      考慮到init函數需要文件的讀取,所以添加了錯誤捕捉.不過通常情況下ipiscnc是不會錯誤的,因為remote_addr返回的必然是個正確格式的ip.

      每當訪問asp時,除了第一次需加載文件外,其余時候只需三四行代碼既可以判定,真正實現了空間換時間.

    1. 上一頁:
    2. 下一頁:
    Copyright © 程式師世界 All Rights Reserved