程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> 關於PHP編程 >> 制作一個自己的二進制IP庫文件

制作一個自己的二進制IP庫文件

編輯:關於PHP編程

一、前言

有做過IP歸屬地查詢功能的朋友應該都有聽說過純真IP庫,純真IP庫查詢類似這樣:

若你僅需要根據IP搜索出用戶的歸屬地文字然後顯示出來,只要按照該IP庫的規則進行二分查找並顯示就OK了。(格式詳解)

但如果你需要根據IP獲取歸屬地文字描述,然後進一步與自己已有的行政地區數據表關聯起來該如何處理呢?

粗看這兩種應該是都可以實現,但是效率呢?都很差!特別是面對並發稍高的應用,這兩種方式都經不起考驗。

為什麼不根據純真IP庫(其他IP庫也可以)的數據與自己的地區數據關聯起來,用自己的地區ID來代替純真IP庫的地區描述,最後制作一個自己的二進制IP庫文件呢?

讓我們進入正題,看看如何根據純真IP庫數據制作一個自己的二進制IP庫文件。

 注:本文只說明大致思路,沒有詳細代碼,謝謝

二、准備工作

我們需要准備好兩部分的數據:

  1. 純真IP庫解壓後的txt文件。

    純真IP庫下載後會有個ip.exe工具,使用上面的解壓即可生成。

    生成的數據如圖1-1,我這個版本有大概444290條。

    

                圖1-1

 

  2. 自己的國家省市級聯數據表。

    這個網上應該比較多,自己進行導入,表結構類似(area_id, area_level, area_name, area_pid),分別代表地區ID,地區等級,地區名稱,父地區ID。

    當然你也可以自己使用不同的結構,不影響我們這次的處理。

 

三、過程 

  數據已經有了,現在來規劃下我們需要生成的IP庫的機構。

  從標題中就知道,我們需要生成的IP庫是二進制的數據包,而不是普通文本文件,那麼我們的IP庫文件結構應該是怎樣的呢?

  如圖所示:

  

  可以看到,我們的結構是這樣的:

    • 頭部。位於文件的前8個字節。前4字節存放32位整數,值為數據部分的開始在文件中的位置;後4字節也存放32位整數,值為數據部分的結束在文件中的位置
    • 主體數據部分。由N個固定結構體組成,每個結構體12字節,為一條IP范圍數據(ip_start, ip_end, area_code)。結構體的三個部分也分別為32位有符號整數,各4字節。(area_code若是量小的話也可以使用1個字符)

  

  IP數據包的結構已經定下來了,後面就是一步步處理了。

    1. 逐條讀取IP文本文件內容,IP轉為32位有符號整數(自定義的ip2long),地區文字分析獲取到最終地區

      a. IP文本文件每行的規則為:前15字節為IP起始地址,後15字節為IP結束地址,最後為地區文字描述。

      b. IP轉為32位有符號整數只占4字節,且解決了PHP函數ip2long在32位與64位系統下值不同的問題,新的函數如下:

 ip2Long32( = ('l', ('l', ( [1

      當然,你也可以自己開發PHP擴展,詳見這邊:http://www.cnblogs.com/iblaze/archive/2013/06/02/3112603.html

      c. 地區需要獲取到各級別地區名稱(包括省、市、縣、區等,這邊國外只保留國家),正則如圖:

      

  

    2. 將獲取到的地區信息轉為地區ID

      這部分處理我不太好描述,因為可能每個人用到的地區都不一樣,但是大致原理就是先根據最低級地區名稱去查找ID(看實際情況,有可能要去掉市、縣之類),若是沒有則查找上一級,如此循環,直到獲取到地區ID。

      若是沒有查找到地區ID,則都歸入未知。

    3. 壓縮,壓縮後的文件約為5.08M

      壓縮規則如圖,format中的值對應pack中的類型:

      

      這邊有個地方必須提示下,由於IP轉為有符號32位整數,則128.0.0.0以後的IP都會為負數,所以需要判斷負數,並放入我們IP庫的前面去,畢竟是使用二分查找,需要為有序數據。

      

    4. 查找IP,使用二分查找,44W條數據最多只需要搜索19次,類似如下:

      

    

    4. 單個測試,看起來速度還可以

      

    5. 簡單壓測看效果

         a. ab壓測,使用本機的ab

      b. 測試腳本在linux測試機(普通PC機)

      c. 壓測腳本如下:

      

      d. 壓測語句: ab -n 10000 -c 50 http://192.168.206.71/ipdata.php?type=php

      

      表現還不錯。呵呵

      


 

  結束了,有什麼更好的方式可以一起討論下,謝謝~

      

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