有時候我們需要判斷某一個IP地址是否屬於一個網段,以決定該用戶能否訪問系統.# u3 x% G9 p) X& o1 U* V
比如用戶登錄的IP是218.6.7.7,而我們的程序必須判斷他是否屬於218.6.0.0/16這個網段(其中/16是新的子網掩碼的表示方式,相當於255.255.0.0)." {0 u t; Y2 G( R ~" X# {5 w
要實現這樣的功能,現在流行的算法是將218.6.0.0和218.6.7.7按256進制換算成10進制並進行比較得出,如先計算出218.6.0.0和218.6.255.255的十進制:218×256×256×256+6×256×256=3657826304,218×256×256×256+6×256×256+255×256×256+255=3657891839。再計算出218.6.7.7的十進:218×256×256×256+6×256×256+7×256+7=3657828103,最後再比較3657828103是否大於等於3657826304和小於等於3657891839。但明顯有一個問題,計算量非常多,值非常大,如果IP地址是61開頭的還好,如果是218開頭的,這將會造成數據溢出而出錯。1 \5 G7 p+ O& S" a" d
其實比較IP是否屬於某一網段,最好的方式就是將IP與網段分別轉為32位二進制,再比較他們的網絡部分是否相同就可以了.asp本身不具備位運行功能,所以要實現這個只有我們手工實現,具體如下:
: D3 m- o8 T9 x2 F. r1 W0 z'將十進制轉為二進制字符串& f; D% k* k r' |
function dec2bin(octNumber)
+ z( P5 Q/ Z6 x! Fvara=octNumber
" t3 I0 \ t: ^& g2 L. r2 G ndo 0 S1 W& R7 B8 u- J3 }
dec2bin=cstr(vara mod 2) & dec2bin7 W0 e9 z) M" S6 [
vara=vara \ 2; x+ P- i$ ?" n }$ ^7 N/ y
loop until vara=0
) a/ M+ ?+ p1 g5 p+ ]! Yend function5 u2 R+ B) }& o
5 X4 a9 k: @0 Z+ e- E+ h
'將二進制字符串填充為8位
( s' ^$ w! b( S7 I2 p+ Z$ }7 h$ efunction pad(str)
0 M7 X+ F2 r4 l- s6 [+ K8 Qpad=right("00000000" & str,8)
+ ~' [( S1 K7 i& jend function
1 b1 |) w5 `9 p% O q/ {* A( N
5 q: C7 O- s4 K. t'判斷是否是一個IP地址5 @! u( S4 L% }( D) Z
function isIp(ipadd)
2 v6 L0 E! f) A* bisIp=false
f8 Y& R4 y( x! y4 Z0 n( u- }: Hset oReg=new RegExp, y) a1 @, }( h# m% ^, R8 p
oReg.IgnoreCase=true
$ Y7 e2 M, {+ Q: e1 MoReg.global=true
( D) r8 z( z4 _- a9 ~oReg.Pattern="(\d{1,4}\.\d{1,4}\.\d{1,4}\.\d{1,4})|(\d{1,4}\.\d{1,4}\.\d{1,4}\.\d{1,4}\/\d{1,2})" h/ k4 n" C# ]
if oReg.test(ipadd) then isIp=true
; {) @$ s" u# Qset oReg=nothing" |: V v, \# _% X5 q ?, P
end function" n# x: ?: h, p1 c# E7 W
# X6 L9 b/ ~3 R# W, n) }/ d
'其中UserIP是我們要檢測的IP
+ I" c8 t5 y: ^3 }' R- b: s'NetIP是要檢測的網段或某個IP,用xxx.xxx.xxx.xxx/N來表示網段,其中N表示子網掩碼位數
9 q! i2 h; P! z5 z9 }# ]0 f6 `8 {+ Q'注,該程序是環球萬維原創程序,所以如果您要轉載,請保留出處信息,謝謝., ?( ^* X0 S* c$ M C- l, r
'程序設計:環球萬維,專業提供域名註冊,虛擬主機服務
4 w, G3 ^) O5 f( Z8 h3 k6 S'網址:http://www.netInter.cn
) v9 \9 n9 h& e) ]$ Q'以上信息與文章正文是不可分割的一部分,所以如果您要轉載本文章,您必須保留以上信息.
: i) a: l+ c/ _, J
7 U! ^7 x" a, i6 V! m5 RFunction check_ip(UserIp,NetIP)! G6 V: E# j, N, |
currentip=UserIp
5 ^8 V5 Q# O' l0 P/ e# hcollection_ips=split(iplist,",";) '將網絡按點分割成4段
: [' h, ^1 T& f* y( ]' [( O! n; _check_ip=false '初始函數值,false假設IP不在這網段
( s2 }5 k& e0 Y9 C- ]NetIP=trim(NetIP)/ q* d4 m0 z- v. F( a
slashPos=inStr(NetIP,"/";)
$ A8 G) K! I q1 X; q M) Q& Dif slashPos=0 then '網段沒含有/符號,他只是一個IP,所以比較比個字符串是否相同就可以了" B' G% g F* U5 e
if NetIP=currentip then
. I: ]4 N" }# @2 d5 L7 Fcheck_ip=true 'check_ip=true表示IP相等
( M1 r W0 Z0 Y' s4 y K1 P# Q: rexit function$ g+ S5 `7 Z* b
end if
+ o6 G/ C6 e" G c* X k) F) k0 zelse( ~/ Z9 T$ F9 ?( v" L
netRang=mid(NetIP,slashPos+1) '得到/後邊的數字) ?9 M u, R4 P
if not isNumeric(netRang) then '/後邊不是數字,格式不正確
$ g9 x7 ?2 `$ x6 o2 [exit function6 h) a# W' W/ H" h7 B. a
end if
p0 {% p5 X1 g7 [netRang=cint(netRang) '將字符轉為數字' |; I9 x" G1 \
if netRang>31 then
2 m; s% z* \5 s& @. J/ U2 g# p0 g" Texit function '/後的數字不能超過32位
8 } c! |) ]9 y( ^2 z7 oend if6 n- A6 T/ \" `3 ?3 l) E* K
ipsets=split(currentip,".";) '將用戶IP按點分成四段
/ ^2 v) w& j2 c& l& I. g- l( {" ]# {0 I
C_IP_BIN=pad(dec2bin(ipsets(0))) & pad(dec2bin(ipsets(1))) & pad(dec2bin(ipsets(2))) & pad(dec2bin(ipsets(3)))6 X9 [0 @" L% Z) h9 c) H8 ^
'上邊這行是將用戶IP地址手工轉換為對應的一個32個字符長的二進制
1 B; M& X! P6 |5 Dipsets=split(NetIP,".") '按上邊的過程將網段IP同樣轉為32個字符長的二進制
' m( p% a+ @+ p5 T% ^" esPos=instr(ipsets(3),"/") '最後一點格式應該是 數字/數字
5 N4 V! W& v: Y% Hif sPos=0 then5 o% I. J6 j: q
exit function+ E6 B4 S: B( Q9 m' l% H
end if( J3 t% a6 M# [% o8 }
ipsets(3)=left(ipsets(3),sPos-1) '得到最後一段/前邊的數字
2 c1 d9 H0 s1 DS_IP_BIN=pad(dec2bin(ipsets(0))) & pad(dec2bin(ipsets(1))) & pad(dec2bin(ipsets(2))) & pad(dec2bin(ipsets(3)))
9 g5 l& o7 n) J: y8 F'將其轉換為32個字符長的二進制
$ g$ E; M. Y2 k) N6 n! @* G6 mif left(C_IP_BIN,netRang) = left(S_IP_BIN,netRang) then '比較網段絡是否相同就可以判斷用戶IP否屬於某個網段了
- A' h ?/ o" E( G0 Echeck_ip=true& o* S3 g3 z: j
end if
5 w' k4 s) h# ~9 p- mend if7 N0 ^" \# n3 m
end function" T, U W5 o, S7 ?
" }2 G5 j4 M6 O! f( W
應用舉例:5 O$ C6 m" R9 m% Z" D" p
3 h2 d0 G2 k& [0 g$ L要判斷61.139.1.1是否在61.139.0.0/16 (255.255.0.0)這個網段
$ c' D8 S) f* N3 n' W9 o% i$ b+ r+ q只需要簡單的使用這個函數就可以了,如:+ W% Z i1 N! c: Q" a" }
: x; p4 w' C. b3 P9 z+ oif check_ip("61.139.1.1","61.139.0.0/16") then6 D( { X# @ I6 @! {1 U% d, G1 v7 q
Response.write "同一網段"
; A+ [" c, C/ D. e7 N% Y& felse
7 B$ i' _0 V Q/ ?Response.write "不是同一網段"
& e3 E6 W0 y' n; K% Y8 A' u2 V* Aend if
8 N; e% b+ w! \) C* H4 ]8 R- C4 i7 u5 R' g( a* K) v
[ 本帖最後由 鼕菇蒸雞 於 2006-8-10 20:13 編輯 ] |
|