1. 问题描述

给定一个IP地址,如何查询其所属的ISP,如:中国移动(ChinaMobile),中国电信(ChinaTelecom),中国铁通(ChinaTietong)?现有ISP的IP地址区段可供下载,比如中国移动的IP地址段

103.20.112.0/22

103.21.176.0/22

111.0.0.0/20

112.0.0.0/10

117.128.0.0/10

120.192.0.0/10

183.192.0.0/10

211.103.0.0/17

211.136.0.0/14

211.140.0.0/15

211.142.0.0/17

211.142.128.0/17

211.143.0.0/16

218.200.0.0/14

218.204.0.0/15

218.206.0.0/15

221.130.0.0/15

221.176.0.0/13

223.112.0.0/14

223.116.0.0/15

223.120.0.0/13

223.64.0.0/11

223.96.0.0/12

36.128.0.0/10

39.128.0.0/10

上述网络地址是CIDR记法:IP地址/网络id位数,其中IP地址分为两部分

  • 网络id
  • 主机id

比如,192.168.23.35/21,其子网掩码为11111111 11111111 11111000 00000000即255.255.248.0,网络ID:192.168.00010111。IP地址103.20.112.168与地址段103.20.112.0/22前22位相匹配,则此IP地址属于中国移动。


2. Trie树实现查询

Trie树使用公共前缀,降低查询时间,减小了存储空间。为了构建Trie树,将IP地址二进制化(32位的二进制)。用于查询的Trie树一棵二叉树,满足以下性质:

  • 非叶子节点的左孩子节点为0,右孩子节点为1;
  • 叶子节点存储IP地址所对应的ISP。

Trie树的Java实现

/*
* Trie树,用于存储、检索ip地址
* 叶子节点标记为ip地址对应的ISP
*/
public class TrieTree {
private Node root = null; //根节点 /*二叉树的节点*/
private static class Node {
String element; //非叶子节点为空 叶子节点标记为ISP
Node[] children; //左孩子节点为0 右孩子节点为1 public Node() {
element = "";
children = new Node[2];
for (int i = 0; i < children.length; i++) {
children[i] = null;
}
}
} public TrieTree() {
root = new Node();
} /*插入ip地址*/
public void insert(Node root, String ipAddress, String isp) {
if(ipAddress.length() > 32) {
System.out.println("ip地址处理错误");
} else {
Node crawl = root;
for(int i=0; i<ipAddress.length(); i++) {
int index = (int) ipAddress.charAt(i) - '0';
if(crawl.children[index] == null) {
crawl.children[index] = new Node();
}
crawl = crawl.children[index];
}
crawl.element = isp;
}
} public void insert(String ipAddress, String isp) {
insert(root, ipAddress, isp);
} /*
* 检索ip地址,返回其所对应的ISP
* 若不在Trie树中,则返回null
* */
public String search(String binaryIP) {
Node crawl = root;
for(int i = 0; crawl.element.length() == 0; i++) {
int index = (int) binaryIP.charAt(i) - '0';
if(crawl.children[index] == null) {
return null;
}
crawl = crawl.children[index];
}
return crawl.element;
}
}

IP地址格式化

下面的IPFormat给出两个方法,实现

  • 将IP地址转变成二进制
  • 从CIDR记法的IP地址中得到网络ID部分
/*
* IP地址CIDR记法:network.host/size
* 比如:103.20.112.0/22
* 功能:将IP地址转换成其network地址
*/ public class IPFormat {
/*将ip地址转换成32位的二进制*/
public static String toBinaryNumber(String ipAddress) {
String[] octetArray = ipAddress.split("\\.");
String binaryNumber = "";
for(String str: octetArray) {
int octet = Integer.parseInt(str, 10);
String binaryOctet = Integer.toBinaryString(octet);
int bolength = binaryOctet.length();
if(bolength < 8) {
for (int i = 0; i < 8 - bolength; i++) {
binaryOctet = '0' + binaryOctet; //补前导0
}
}
binaryNumber += (binaryOctet);
}
return binaryNumber;
} /*获取network地址部分*/
public static String getNetworkAddress(String cidrAddress) {
String[] cidrArray = cidrAddress.split("/");
String binaryNumber = toBinaryNumber(cidrArray[0]);
int size = Integer.parseInt(cidrArray[1]);
return binaryNumber.substring(0, size);
} /*main方法用于测试*/
public static void main(String[] args) {
String ip = "103.20.112.0/20";
String bn = getNetworkAddress(ip);
System.out.println(bn);
}
}

Trie树的应用:查询IP地址的ISP的更多相关文章

  1. 【VB.NET】通过 IPIP.NET 数据库来查询IP地址

    上一次介绍了利用纯真数据库查询IP地址详细信息的方法.然而纯真数据库是由网友反馈所提供的,很多数据描述并不准确,所以我上网找了一些其他的IP数据库,最后就找到了 ipip.net 这个网站所提供的IP ...

  2. 【VB.NET】利用纯真IP数据库查询IP地址及信息

    几年前从某个博客抄来的,已经忘记原地址了,如果需要C#版的,可以在博客园搜到吧.我因为自己用,所以转换为了VBNET代码,而且也放置了很久,今天无意间翻出来,就分享给大家吧. 首先,先下载 纯真数据库 ...

  3. 查询ip地址归属地

    查询ip地址归属地方法: curl ip.cn/$ip 如果没有返回,试试地址写全: curl https://www.ip.cn/$ip 如:

  4. Mac通过域名查询IP地址

    Mac通过域名查询IP地址 方法一:使用Mac自带的"网络实用工具" 步骤: 搜索"网络使用工具",并打开: 点击LookUp,输入互联网地址,点击Lookup ...

  5. 在windows系统和linux系统中查询IP地址命令的不同

    在linux和windows系统上查询IP地址的命令是不一样的.         在linux中的命令行模式下,输入ifconfig即可查询到IP.而在windows系统下要查询IP地址需要先打开do ...

  6. php查询ip地址来源归属地的脚本

    <?php header('Content-Type:text/html;charset=utf-8'); if($_GET['sub']){ $ip = $_GET['ip']; $msg = ...

  7. 手机归属地查询-IP地址查询-身份证查询-域名备案查询--Api接口

    使用这些接口是需要密钥的 公共密钥 appkey: 10003  secret: d1149a30182aa2088ef645309ea193bf  生成后sign: b59bc3ef6191eb9f ...

  8. Linux socket编程 DNS查询IP地址

    本来是一次计算机网络的实验,但是还没有完全写好,DNS的响应请求报文的冗余信息太多了,不只有IP地址.所以这次的实验主要就是解析DNS报文.同时也需要正确的填充请求报文.如果代码有什么bug,欢迎指正 ...

  9. [Xcode 实际操作]八、网络与多线程-(11)使用同步Post方式查询IP地址信息

    目录:[Swift]Xcode实际操作 本文将演示如何通过Post请求,同步获取IP地址信息. 一旦发送同步请求,程序将停止用户交互,直至服务器返回数据. 在项目导航区,打开视图控制器的代码文件[Vi ...

随机推荐

  1. wpf下datagrid使用过程中需要注意的几点(一)

    MainWindow.xaml中的代码如下: <DataGrid CanUserAddRows="False" ItemsSource="{Binding}&quo ...

  2. 如何在IIS7/7.5上配置IISADMPWD

    问题 很多IIS用户还记得在早期的IIS版本上有一个web应用, IISADMPWD. 该应用是与IIS5 和IIS6一起发布的. 主要用于为域用户提供修改密码的功能, 同时也可以修改本机用户的密码. ...

  3. java笔试题(金山网络)

    今天参加金山的校园招聘,java笔试,回来仔细研究实现一下: 题目1:工厂两条生产线,三个工人,生产线上可以最多存放m个产品,当生产线满时,机器停止生产,等产品线不满时才继续生产,每条产线上一次只能允 ...

  4. C#Light Unity逻辑热更新解决方案0.20 发布

    之前一直是Beta,这次已经实际运用到项目中间了,去掉beta状态 在项目中使用面对一些新的问题,还有以前没注意的bug. 更新列表 一.增加类中类的支持 二.增加对foreach的支持,同C#语法 ...

  5. 用curl向指定地址POST一个JSON格式的数据

    昨天的一个任务,用POST 方式向一个指定的URL推送数据.以前都用的数组来完成这个工作. 现在要求用json格式.感觉应该是一样的.开写. <?php $post_url = "ht ...

  6. 《30天自制操作系统》笔记(01)——hello bitzhuwei’s OS!

    <30天自制操作系统>笔记(01)——hello bitzhuwei's OS! 最初的OS代码 ; hello-os ; TAB=4 ORG 0x7c00 ; 指明程序的装载地址 ; 以 ...

  7. 十分钟搞定CSS选择器

    在最近的web开发中是不是就会用到一些选择器,发现很多尤其是CSS3新增的不太熟悉,在此总结一下. 优先级 不同级别 1. 在属性后面使用 !important 会覆盖页面内任何位置定义的元素样式. ...

  8. 解决方法of未在本地计算机上注册“Microsoft.Jet.OLEDB.4.0”提供程序

    在开发的一个报表转换功能涉及到Excel97-2003(.xls)文件的导入.使用oledb来读取excel数据.代码为: public static DataSet LoadDataFromExce ...

  9. CSS水平垂直居中的几种方法2

    直接进入主题! 一.脱离文档流元素的居中 方法一:margin:auto法 CSS代码: div{ width: 400px; height: 400px; position: relative; b ...

  10. Oracle使用小记

    windows下Oracle必须要启动的服务 Oracle ORCL VSS Writer Service:Oracle卷映射拷贝写入服务,VSS(Volume Shadow Copy Service ...