请选择 进入手机版 | 继续访问电脑版

 找回密码
 注册

只需一步,快速开始

蓝色理想 最新研发动态 用悬赏 三天解决问题 解决访问速度慢 论坛支持农历生日 - 地图任务 - 给官方提建议

论坛活动及任务 归纳网站最新活动 请更新论坛注册邮件 第一季积分兑换活动 - 12周年上海聚会照片

万元奖励等你拿——点点网模板设计大赛 畅销译文征名——让最火的畅销书,印上你的标签 看看有才会员作品,欢迎打分拍砖

查看: 9519|回复: 24

[asp] 快速判断IP是电信 OR 网通 [复制链接]

etherdream 楼主
帖子
116
体力
549
威望
8
发表于 2009-12-26 12:59:26 |显示全部楼层
判断IP的来源是电信还是网通,常用于站点的后台程序.典型的做法当然是查询数据库,数据库里保存着网通(或电信)的IP范围,然后通过范围搜索来决定该IP是否在网通(或电信)的区间内.不过每次都得查询数据库,效率显然很低.

    不多废话,直接开始说一种超快的算法吧.既然要极快,莫过于o(1)的复杂度,所以开辟一巨大的缓冲区,用经典的空间换时间,通过查表一步即可判定.那如何定义表的大小,还有key?先从CNC.txt这个文件看起.
(http://www.etherdream.com/FunnyScript/IPRange/CNC.txt)

    这个文件是中国网通的路由表.仔细观察下,不难发现掩码位数最高不超过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时,除了第一次需加载文件外,其余时候只需三四行代码既可以判定,真正实现了空间换时间.

    测试地址: http://www.etherdream.com/FunnyScript/IPRange/IP.ASP

    (另附上将路由表转换成缓存文件的c代码:http://www.etherdream.com/FunnyScript/IPRange/IP.c)

[ 本帖最后由 etherdream 于 2009-12-26 13:01 编辑 ]
帖子
82
体力
234
威望
0
居住地
浙江省 杭州市
发表于 2009-12-26 21:52:48 |显示全部楼层
留个记号。。。收藏起来。。。以后慢慢看
黄金位置广告招商!

cityhawk

中级会员

帖子
89
体力
756
威望
0
居住地
湖北省 黄石市
发表于 2009-12-29 09:50:26 |显示全部楼层
测试结果不太对呢?

我的线路是移动的,怎么显示成了电信的呢?

是不是路由表有问题。
http://cndawn.com
likr 
帖子
1
体力
12
威望
0
发表于 2009-12-29 11:50:32 |显示全部楼层

回复 2# bcinmaster 的帖子

留个记号。。。收藏起来。。。以后慢慢看

浪子回头8

高级会员  

帖子
337
体力
874
威望
0
居住地
陕西省 西安市
发表于 2009-12-30 17:21:56 |显示全部楼层
有些地方IP不准,我们公司用的铁通就这样
www.mini88s.com
帖子
30
体力
114
威望
0
发表于 2010-1-5 15:41:16 |显示全部楼层
好,谢!!!!!!!!!!!

蓝色月球

金牌会员

帖子
753
体力
4601
威望
3
发表于 2010-1-7 20:03:10 |显示全部楼层
3楼就没看楼主的帖子主题和内容嘛,算法里只有1 bit表示是网通,不是网通就是电信,呵呵
所以,如果要加移动,联通,卫通。。。。恐怕这个文件还得长个几倍才行
此人来自月球

IComputer

中级会员

帖子
55
体力
252
威望
1
居住地
湖南省 常德市
发表于 2010-3-31 08:55:26 |显示全部楼层
先留个位置 慢慢看
帖子
7
体力
34
威望
0
发表于 2010-4-5 22:36:03 |显示全部楼层
我自己也做了一个,并且应用到了网站之中,思路是这样的,首先得到客户端的IP地址,再在数据库中去查询这个IP地址所对应的物理地址,注:这里所说的数据库并不是mysql mssql之类的,而是腾讯QQ显IP这个软件中带的那个文件(QQWry.Dat)

查询速度非常的快.发一个后台管理监控到的列表图:

[ 本帖最后由 weidamao 于 2010-4-5 22:38 编辑 ]
附件: 你需要登录才可以下载或查看附件。没有帐号?注册
帖子
210
体力
608
威望
0
发表于 2010-4-5 22:42:52 |显示全部楼层
哈哈。。N年了。一直不知道原来我在蓝色上原来有两个号。呵呵。。刚发帖是还奇怪呢。为什么我只发了3篇帖子呢。改用我7级大号登陆了。。。
爱extjs http://www.wo500.com
帖子
57
体力
782
威望
0
发表于 2010-4-7 10:41:42 |显示全部楼层

回复 9# weidamao 的帖子

能否讲解下你是如何做的?
帖子
210
体力
608
威望
0
发表于 2010-4-8 20:13:33 |显示全部楼层
我是搞JAVA开发的。主要是的核心代码就是使用JAVA代码去读取QQWry.Dat这个文件,当然 有一定的规则 及构建查询缓存等。网上你可搜索到类似的效果。
爱extjs http://www.wo500.com
帖子
27
体力
238
威望
0
居住地
黑龙江省 哈尔滨市
发表于 2010-4-9 14:58:19 |显示全部楼层
用IP数据库就好了那个是纯真版...QQwry.Dat 经常更新的
帖子
27
体力
238
威望
0
居住地
黑龙江省 哈尔滨市
发表于 2010-4-9 14:58:53 |显示全部楼层
把我的联通IP变成电信的了 。。
帖子
210
体力
608
威望
0
发表于 2010-4-16 19:27:09 |显示全部楼层
目前我正在找全球的IP数据库。QQwry.Dat记录中国的准确率还是很高的。基本上是90%以上。
爱extjs http://www.wo500.com

小鱼的理想

银牌会员  

帖子
567
体力
2766
威望
1
居住地
山东省 济宁市
发表于 2010-12-10 11:58:20 |显示全部楼层
想请教在PHP下面该怎样实现啊?公司网站要做一个镜像站,根据客户的IP地址自动选择,而且不想用JS的方式,首页做了优化,还不想将首页换了,我就行先判断如果是网通的话,就不跳转,如果是电信的话,就跳转到镜像站。
帖子
658
体力
1598
威望
1
居住地
云南省 昆明市
发表于 2010-12-10 23:15:35 |显示全部楼层
有一定的局限性

面条爱兔子

银牌会员

帖子
1014
体力
2451
威望
3
居住地
湖南省 长沙市
发表于 2010-12-11 09:52:37 |显示全部楼层
楼上说得对,我也在用这个东东。

leye小妖

初级会员  

帖子
388
体力
160
威望
0
居住地
河南省 郑州市
发表于 2010-12-12 11:19:07 |显示全部楼层
高手真多。。。

[ 本帖最后由 suiyuan21012 于 2010-12-12 11:20 编辑 ]
小妖巡山了
帖子
19
体力
97
威望
0
居住地
黑龙江省 哈尔滨市
发表于 2010-12-13 20:38:58 |显示全部楼层
是啊,学习了,呵呵
帖子
6179
体力
2798
威望
0
居住地
湖南省 长沙市
发表于 2010-12-13 21:43:22 |显示全部楼层
收藏满了  回帖收藏
帖子
120
体力
409
威望
0
居住地
浙江省 宁波市
发表于 2010-12-18 10:28:27 |显示全部楼层
收藏满了  回帖收藏
5jnb 
帖子
7
体力
21
威望
0
发表于 2010-12-18 15:20:32 |显示全部楼层
直接用js就判断出来了,没那么复杂,
或者用dns智能判断
帖子
13
体力
108
威望
0
居住地
山东省 德州市
发表于 2010-12-21 11:33:47 |显示全部楼层
收藏了,呵呵。。。
付出-回报
帖子
7
体力
34
威望
0
发表于 2011-1-11 09:17:48 |显示全部楼层
原帖由 mental 于 2010-12-10 11:58 发表
想请教在PHP下面该怎样实现啊?公司网站要做一个镜像站,根据客户的IP地址自动选择,而且不想用JS的方式,首页做了优化,还不想将首页换了,我就行先判断如果是网通的话,就不跳转,如果是电信的话,就跳转到镜像站。 ...


最近加班+出差.很久没上蓝色了..

你的这个问题不知道你解决了没.如果解决了可以拿出来分享一下嘛..我的个人建议是这部份工作不要让我们自己来做.建议采用"智能DNS".比如国人的https://www.dnspod.cn/  效果还不错。
您需要登录后才可以回帖 登录 | 注册

Archiver|手机版|安久科技提供CDN|blueidea.com ( 京ICP备05002321号 )  

GMT+8, 2012-1-10 14:33 , Processed in 0.547049 second(s), 8 queries , Gzip On.

Powered by Discuz! X2

© 2001-2011 Comsenz Inc.

回顶部