Skip to content

Instantly share code, notes, and snippets.

@jxinging
Last active August 29, 2015 14:04
Show Gist options
  • Select an option

  • Save jxinging/997a641a778dea6f211a to your computer and use it in GitHub Desktop.

Select an option

Save jxinging/997a641a778dea6f211a to your computer and use it in GitHub Desktop.
17monipdb 格式解码
#coding: utf8
"""17monipdb 解码"""
import socket
import struct
_unpack_ulong_little = lambda x: struct.unpack("<L", x)
_unpack_ulong_big = lambda x: struct.unpack(">L", x)
class IPDB(object):
def __init__(self, datafn=None):
if not datafn:
datafn = "17monipdb.dat"
self._datafn = datafn
self._datafile = None
self._index_end = None
self._index = None
self._cache = dict()
def _do_init(self):
if self._datafile is not None:
return
self._datafile = open(self._datafn, 'rb')
# 头4字节保存着索引数据的结束位置
self._index_end = _unpack_ulong_big(self._datafile.read(4))[0]
index_len = self._index_end - self._datafile.tell() # 索引数值的实际长度
self._index = self._datafile.read(index_len)
def find(self, host):
ip_str = socket.gethostbyname(host)
ip_int = socket.inet_aton(ip_str)
if self._datafile is None:
self._do_init()
if ip_int in self._cache:
return self._cache[ip_int]
# 通过IP地址第一段找到一级索引的位置。一个索引数据占4字节,所以要乘以4
this_index1_pos = int(ip_str.split(".")[0]) * 4
index2_offset = 1024 # index2 在 index 里的偏移
index2_len = len(self._index) - index2_offset
# 通过一级索引找到2级索引的位置
this_index2_num = _unpack_ulong_little(self._index[this_index1_pos:this_index1_pos+4])[0]
# 二级索引一个索引数值占8字节
this_index2_start = this_index2_num * 8
curr_pos = this_index2_start
this_index2_pos = None
while curr_pos < index2_len:
abs_index_pos = curr_pos + index2_offset
if self._index[abs_index_pos:abs_index_pos+4] >= ip_int:
this_index2_pos = abs_index_pos+4
break
curr_pos += 8
else:
return None
data_pos = _unpack_ulong_little(self._index[this_index2_pos:this_index2_pos+3]+"\x00")[0]
data_len = ord(self._index[this_index2_pos+3])
self._datafile.seek(self._index_end+data_pos-1024)
self._cache[ip_int] = self._datafile.read(data_len).decode("utf8")
return self._cache[ip_int]
ipdb = IPDB()
find = ipdb.find
if __name__ == "__main__":
print find("tool.17mon.cn")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment