`
dragonsoar
  • 浏览: 203992 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

java IP库实现

阅读更多

我的官方微博:www.weibo.com/vanwelldotcn

我的官方扣群:102934900

 

    笔者现在主要从事移动互联网相关的一些架构工作,并且负责现在公司内部的平台架构的搭建,那么做移动互联网就一定会涉及到移动终端的IP访问记录,并跟据IP进行定向的广告投放。

        比如现在通地IP可以直接获取IP所对应的省份,那么数据结构应该如下:

        IP | 省份

 

    上面只是笔者模拟的一个表结构,那么具体的IP对应省份,是对终端客户登录时后台DB保存的记录;但是服务器端的IP库,肯定是如下的一个IP段结构

        IP开始段 | IP结束段 | 省份

 

    笔者通过H2内存数据库加载了上面的IP库,然后进行了压力测试;结果发现,在压力大的情况下性格会下降的非常厉害,其实笔记收集到的IP库大小只有40多W行数据而已,50M的数据量。

    在这种情况下,笔者就通过另一种方法实现了IP库段的查询,性能达到了20W+TPS,只是在奔腾双核的机器下面的测试结果,思路如下:

    1.通过TreeMap实现

    2.以IP库的起始段为key(IP库的IP地址转化成long型)

    3.取出比目标IP小,离的最近的IP对应[key值]

    4.然后将查找到的value值和目标IP值进行范围比较

    5.符合则对应此IP段,不符合则未查找到IP库对应的范围地址

 

RangeRow.java
public class RangeRow<T extends Comparable, V> implements Serializable {
private static final long serialVersionUID = -289623726849550889L;
private T begin;
private T end;
private V value;
private Object attachment;

public T getBegin() {
return begin;
}

public void setBegin(T begin) {
this.begin = begin;
}

public T getEnd() {
return end;
}

public void setEnd(T end) {
this.end = end;
}

public V getValue() {
return value;
}

public void setValue(V value) {
this.value = value;
}

public Object getAttachment() {
return attachment;
}

public void setAttachment(Object attachment) {
this.attachment = attachment;
}

}

 

 

IpProvinceRow.java
public class IpProvinceRow extends RangeRow<Long, String> {
private static final long serialVersionUID = 8411106544005822554L;

private String city;

public String getCity() {
return city;
}

public void setCity(String city) {
this.city = city;
}

}

 

 

 

RangeSearchEngine.java
public class RangeSearchEngine<T extends Comparable, V> {
	private TreeMap<T, RangeRow<T, V>> cache = new TreeMap<T, RangeRow<T, V>>();

	@SuppressWarnings("unchecked")
	public V getValue(T key) {
		//
		RangeRow<T, V> row = getRow(key);
		if (row == null) {
			return null;
		}

		//
		T end = row.getEnd();
		if (end == null) {
			return null;
		}
		if (end.compareTo(key) > 0) {
			return row.getValue();
		}

		return null;
	}

	public RangeRow<T, V> getRow(T key) {
		if (key == null) {
			return null;
		}
		//
		Entry<T, RangeRow<T, V>> entry = cache.floorEntry(key);
		if (entry == null || entry.getValue() == null) {
			return null;
		}
		//
		return entry.getValue();
	}

	public void putAll(Map<T, RangeRow<T, V>> map) {
		cache.putAll(map);
	}

	public RangeRow<T, V> put(RangeRow<T, V> row) {
		return cache.put(row.getBegin(), row);
	}

	public RangeRow<T, V> remove(T key) {
		return cache.remove(key);
	}

	public void clear() {
		cache.clear();
	}

	public TreeMap<T, RangeRow<T, V>> getCache() {
		return cache;
	}

	public TreeMap<T, RangeRow<T, V>> setCache(TreeMap<T, RangeRow<T, V>> newCache) {
		if (newCache == null) {
			throw new NullPointerException();
		}
		//
		TreeMap<T, RangeRow<T, V>> before = cache;
		cache = newCache;
		//
		return before;
	}
}
 

 

IpProvinceSearchEngine.java
public class IpProvinceSearchEngine extends RangeSearchEngine<Long, String> {
	public static final String SPLITER = "\\|";
	//
	private Logger logger = LoggerFactory.getLogger(getClass());

	/**
	 * @Title: load
	 * @Description: 载入Ip库文件
	 * @author Administrator
	 * @param dataFile
	 * @throws FileNotFoundException
	 * @throws IOException
	 * @return void 返回类型
	 */
	public void load(String dataFile) throws FileNotFoundException, IOException {
		TreeMap<Long, RangeRow<Long, String>> map = new TreeMap<Long, RangeRow<Long, String>>();
		BufferedReader file = new BufferedReader(new FileReader(dataFile));
		try {
			//
			String content = null;
			while ((content = file.readLine()) != null) {
				String[] parts = content.split(SPLITER);
				if (parts.length < 3) {
					logger.warn("parse line failed, " + content);
					continue;
				}
				//
				try {
					IpProvinceRow row = new IpProvinceRow();
					row.setBegin(Long.valueOf(parts[0]));
					row.setEnd(Long.valueOf(parts[1]));
					row.setValue(parts[2]);
					//
					if (parts.length > 3) {
						row.setCity(parts[3]);
					}
					//
					map.put(row.getBegin(), row);
				} catch (Exception e) {
					logger.warn("parse row failed:" + content);
				}
			}
			//
			setCache(map);
		} finally {
			try {
				file.close();
			} catch (IOException e) {
			}
		}
	}

	/**
	 * @Title: getProvince
	 * @Description: 获取省份信息
	 * @author Administrator
	 * @param @param ip
	 * @param @return 设定文件
	 * @return String 返回类型
	 */
	public String getProvince(String ip) {
		//
		long intIp = convertIpToLong(ip);
		//
		return getValue(intIp);
	}

	/**
	 * @Title: convertIpToLong
	 * @Description: 转换Ip为256进制整数
	 * @author Kolor
	 * @param ip
	 * @return long
	 */
	public static long convertIpToLong(String ip) {
		String[] checkIp = ip.split("\\.", 4);
		long intIp = 0;

		for (int i = 3, j = 0; i >= 0 && j <= 3; i--, j++) {
			intIp += Integer.parseInt(checkIp[j]) * Math.pow(256, i);
		}
		return intIp;
	}

	public static void main(String[] args) throws FileNotFoundException, IOException {
		String file = "C:\\Users\\Administrator.PC-20110801LBXQ\\Desktop\\ip\\ip.data";
		IpProvinceSearchEngine engine = new IpProvinceSearchEngine();
		//
		long beginTime = System.currentTimeMillis();
		engine.load(file);
		long endTime = System.currentTimeMillis();
		System.out.println("load cost " + (endTime - beginTime));
		//
		System.out.println(engine.getProvince("202.101.15.61"));
	}
}

 

附件中是已经收集好的IP库,不能保证最全,但是已经比较全了。:)

希望大家喜欢这个工具类,比较实用;且性能较高,希望有同样数据段查找的数量有限的需求也可以采用类似的方案。

 

分享到:
评论
2 楼 dragonsoar 2013-02-05  
Sunny_kaka 写道

不知道有没有比较好和稳定的查询ip和对应省份关系的web service服务?

有了这个就不和web service了吧?这个多快啊,web service要走网络很慢的了吧
1 楼 Sunny_kaka 2013-02-04  

不知道有没有比较好和稳定的查询ip和对应省份关系的web service服务?

相关推荐

    java根据ip获取国家、地区名称,附带ip地址库

    java根据ip获取国家、地区名称,附带ip地址库

    Java实现IPV6地址查询

    Java实现IPV6地址查询 Java IP V6 ipv6 地域 地址 查询 地址查询 使用ZX公网IPv6库 20120916版

    Java获取IP归属地

    一、ip2region,一个离线IP地址定位库和IP定位数据管理框架,10微秒级别的查询效率,提供了众多主流编程语言的 xdb 数据生成和查询客户端实现。 二、mica-ip2region,如梦技术基于ip2region做了封装,效率更高,使用...

    BIP39:BIP0039的Java微库实现

    使用以下两个存储库之一: repositories { jcenter() } 要么: repositories { maven { url 'https://dl.bintray.com/novacrypto/BIP/' } } 添加依赖项: dependencies { compile 'io.github.novacrypto:BIP...

    java获取IP地址工具类

    利用淘宝IP地址库实现的利用IP获取用户所在地工具类

    snmpv3 java实现

    java实现的简单网络管理协议!附件是整个工程,下载下来配置ip就可以运行,附有mib库,支持snmpV1,V2,V3版本协议!绝对是好资源,为了兼容移动的网络设备控制,研究了一段时间,现分享出来。不懂得可以找我

    java实现纯真IP数据库的接口源码

    该接口内直接封装了直接调用QQWry.dat的源码。可以直接调用哦

    IP实现定位

    根据Ip实现定位

    java源码包---java 源码 大量 实例

     Java实现的FTP连接与数据浏览程序,实现实例化可操作的窗口。  部分源代码摘录:  ftpClient = new FtpClient(); //实例化FtpClient对象  String serverAddr=jtfServer.getText(); //得到服务器地址  ...

    java开源包4

    jSIP这个Java包目标是用Java实现SIP(SIP:Session Initiation Protocol)协议及SIP协议的其它扩展部 分。 Java表达式语法解析库 parboiled parboiled 是一个纯Java库提供了一种轻量级,易于使用,功能强大和优雅的PEG...

    EEIP.Java:Java 实现的以太网/IP 兼容库-开源

    用于 .NET 实现的以太网/IP 兼容库 用于与以太网/IP 设备(目标)进行数据交换 支持显式和隐式消息传递 支持 IO 扫描器和显式消息客户端功能 带有 CIP 定义对象的对象库 提供一种访问以太网/IP 的简单方法对以太网/...

    JAVA上百实例源码以及开源项目

    百度云盘分享 ... Java实现的FTP连接与数据浏览程序,实现实例化可操作的窗口。  部分源代码摘录:  ftpClient = new FtpClient(); //实例化FtpClient对象  String serverAddr=jtfServer.getText();...

    JAVA上百实例源码以及开源项目源代码

     Java实现的FTP连接与数据浏览程序,实现实例化可操作的窗口。  部分源代码摘录:  ftpClient = new FtpClient(); //实例化FtpClient对象  String serverAddr=jtfServer.getText(); //得到服务器地址  ...

    java开源包3

    jSIP这个Java包目标是用Java实现SIP(SIP:Session Initiation Protocol)协议及SIP协议的其它扩展部 分。 Java表达式语法解析库 parboiled parboiled 是一个纯Java库提供了一种轻量级,易于使用,功能强大和优雅的PEG...

    Java实现Des加密(不用加载包)

    Java实现Des加密(不用加载包),有完整S盒子。 部分代码如下: ackage desJava; import java.util.*; public class Des { byte[] bytekey; public Des(String strKey) { this.bytekey = strKey.getBytes();...

    JAVA基于SNMP网络设备MIB信息采集(论文+源代码)

    设计中运用Java语言,运用Java-Applet技术,其存储在一个运行有Tomcat的服务器上,以接受用户请求,使用户能在任何一个支持Java运行时的浏览器上进行使用。系统在设定设备IP地址及端口号和读写共同体名后能查看相应...

    Springboot集成IP地址属地解析

    Springboot工程根据URL输入获取IP归属地,直接运行:java -jar dust-ip2region-1.0.0-SNAPSHOT.jar 端口:9090 启动后,样例:http://127.0.0.1:9090/index/convert/182.151.251.3 其中{182.151.251.3} 就是需要解析...

    JSIP2:Java 的 SIP2 库。-开源

    JSIP2 是一个开源 (MIT) 库,它实现了 3M SIP 第 2 版协议,包括用于 SIP2 客户端的 3M SIP2 扩展。 该库包含基于 SIP2 客户端套接字的实现所需的功能,支持所有 SIP2 消息和字段,还包括 3M SIP2 扩展中定义的字段...

    java源码包4

     Java实现的FTP连接与数据浏览程序,实现实例化可操作的窗口。  部分源代码摘录:  ftpClient = new FtpClient(); //实例化FtpClient对象  String serverAddr=jtfServer.getText(); //得到服务器...

Global site tag (gtag.js) - Google Analytics