有時候我們需要判斷某一個IP地址是否屬於一個網段,以決定該用戶能否訪問系統.
: I# [' N% ^2 _比如用戶登錄的IP是218.6.7.7,而我們的程序必須判斷他是否屬於218.6.0.0/16這個網段(其中/16是新的子網掩碼的表示方式,相當於255.255.0.0).
! R+ m' `( z: `8 h* M( O' p8 u& t要實現這樣的功能,現在流行的算法是將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開頭的,這將會造成數據溢出而出錯。- W1 ?2 L6 X0 g- o8 i8 C; Z+ d
其實比較IP是否屬於某一網段,最好的方式就是將IP與網段分別轉為32位二進制,再比較他們的網絡部分是否相同就可以了.asp本身不具備位運行功能,所以要實現這個只有我們手工實現,具體如下: % k/ f. ]: T* ]: u9 a a, z
'將十進制轉為二進制字符串
" X: Z5 N" J1 b9 Sfunction dec2bin(octNumber)
8 \9 I7 v8 ?% _# @% F: T2 w) {* I) Jvara=octNumber
# g/ T6 N4 T$ a3 ]! edo 9 ^! g; C5 y, \) I( s
dec2bin=cstr(vara mod 2) & dec2bin8 v7 p* \1 H$ v" }# e2 a- H; r6 J; X
vara=vara \ 2
; J" D1 F! ?$ {6 f: m2 dloop until vara=0
& I1 `% l1 I2 C( o4 ^2 ?end function; j4 R9 @/ W- H8 Y% f- R* d
9 o9 s7 E g7 O8 A/ H'將二進制字符串填充為8位
* L! q) _6 Z- B! j% z0 H( b2 Nfunction pad(str)0 q. a0 r# F/ U. {9 T8 F
pad=right("00000000" & str,8)
7 ], Q% A R i2 p* T: [2 Zend function7 i+ m8 p! q5 B1 c9 g+ t
6 `# z& s7 V' Z
'判斷是否是一個IP地址
( h/ Y' \1 O$ V" Gfunction isIp(ipadd)
: ^" P& ]& Y& V( lisIp=false
7 o0 r2 y9 A( P& w# b L$ iset oReg=new RegExp
8 Z. D+ F" Q) s1 x4 C; E2 }oReg.IgnoreCase=true
5 Y4 Y+ N$ g+ N6 F0 V7 K7 v2 CoReg.global=true! `# D( c) N) u: f% O5 {' `
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})"( ^) p# \. S. D6 V9 u
if oReg.test(ipadd) then isIp=true% z& W9 R. _- ^1 j
set oReg=nothing- e% t$ B2 i. V
end function0 N ~0 ?6 D$ G+ N, D) E
6 R9 p" h% ]* I2 j' f
'其中UserIP是我們要檢測的IP/ w B$ \0 O G& Q
'NetIP是要檢測的網段或某個IP,用xxx.xxx.xxx.xxx/N來表示網段,其中N表示子網掩碼位數 3 B' {+ C! @) e V
'注,該程序是環球萬維原創程序,所以如果您要轉載,請保留出處信息,謝謝.' |+ o ~1 U- X# r1 L. T
'程序設計:環球萬維,專業提供域名註冊,虛擬主機服務7 p- h& u$ x; N8 s
'網址:http://www.netInter.cn! b9 r' Y6 |4 R; V
'以上信息與文章正文是不可分割的一部分,所以如果您要轉載本文章,您必須保留以上信息.& p! b, u. @. Z& A, g
$ `, k$ a( |. B# Q0 ~Function check_ip(UserIp,NetIP)
3 W6 }( `( ]! j+ O+ |! i: ^currentip=UserIp/ w: `7 {7 t5 ?' y; l* {" S' A' J: U
collection_ips=split(iplist,",";) '將網絡按點分割成4段) X4 G' x/ p. ]: `' |8 ~+ Y
check_ip=false '初始函數值,false假設IP不在這網段! J+ N0 H) {) Z) ~
NetIP=trim(NetIP)
1 A1 d" T: h1 ]& V( \! J' i% ~1 yslashPos=inStr(NetIP,"/";)9 P! K$ v# f0 K a, G7 j" B6 G
if slashPos=0 then '網段沒含有/符號,他只是一個IP,所以比較比個字符串是否相同就可以了 F% t. r8 D u% y/ F+ I
if NetIP=currentip then
1 k7 P8 e8 q# Jcheck_ip=true 'check_ip=true表示IP相等
' f0 E8 z( a) X3 m2 ]& @: Rexit function
% [, k# Z/ J" m; e+ v/ @end if
+ e4 ~* x$ G& ?% S$ [else3 _ l* @! g+ {. S2 c
netRang=mid(NetIP,slashPos+1) '得到/後邊的數字2 v4 D3 K8 W0 C7 k2 J1 n
if not isNumeric(netRang) then '/後邊不是數字,格式不正確
) ] o# B8 z; s+ s, Z3 }; }exit function
: o2 v* }, K. T' F# q' ~0 {( y( oend if$ W2 L9 ?) |; a
netRang=cint(netRang) '將字符轉為數字
5 ~* l, m, E3 c% `8 Kif netRang>31 then- Y- x( s m: G9 `1 f- J/ t; g
exit function '/後的數字不能超過32位
+ G3 V: J+ \ G( Cend if3 A: b3 L; \, B$ I- d7 i" h9 y
ipsets=split(currentip,".";) '將用戶IP按點分成四段
: [$ | K9 p. ^+ h [ H$ b9 r- M7 C9 c5 H" Y1 I
C_IP_BIN=pad(dec2bin(ipsets(0))) & pad(dec2bin(ipsets(1))) & pad(dec2bin(ipsets(2))) & pad(dec2bin(ipsets(3)))
9 E" _6 Z7 h: |. s. c'上邊這行是將用戶IP地址手工轉換為對應的一個32個字符長的二進制5 ?$ O% l9 d2 V0 G6 A! i, s- S7 _
ipsets=split(NetIP,".") '按上邊的過程將網段IP同樣轉為32個字符長的二進制
' i4 f: S5 I6 X/ U1 P2 G: \4 N* hsPos=instr(ipsets(3),"/") '最後一點格式應該是 數字/數字5 \) G `5 Z5 y9 s
if sPos=0 then
5 s C, V! D4 w- z" eexit function' G. W: T3 n7 E% |8 G: Q' |
end if* j- Y! G: V3 j t8 U6 a
ipsets(3)=left(ipsets(3),sPos-1) '得到最後一段/前邊的數字+ g6 } w" A" u+ W# K9 ?
S_IP_BIN=pad(dec2bin(ipsets(0))) & pad(dec2bin(ipsets(1))) & pad(dec2bin(ipsets(2))) & pad(dec2bin(ipsets(3)))( ]2 g8 R M0 B$ v
'將其轉換為32個字符長的二進制/ E5 _: N6 r: u0 U+ u! T
if left(C_IP_BIN,netRang) = left(S_IP_BIN,netRang) then '比較網段絡是否相同就可以判斷用戶IP否屬於某個網段了
7 B- A1 w6 T9 t; M4 [. Rcheck_ip=true
6 }1 Z* H0 |" ]; t3 @end if
, L2 g$ e+ V9 B4 z+ P8 xend if$ B# b( u; F: p5 R8 a
end function
8 E# f9 K( @/ n& i# g- W- x; x5 S0 r% G7 i5 ^: q* F
應用舉例:! b. o! ?6 V0 D$ ?- q6 E) I" P
3 F: t: w: Z/ h8 Z/ s6 g% s. |要判斷61.139.1.1是否在61.139.0.0/16 (255.255.0.0)這個網段4 F7 k# q+ z4 z- N3 }! k
只需要簡單的使用這個函數就可以了,如:0 o5 A. T3 E# b- K7 D
/ l+ B0 n. v! h0 C
if check_ip("61.139.1.1","61.139.0.0/16") then
3 u+ @* c4 {$ M, E. o5 H/ \* PResponse.write "同一網段"
% r0 s% R# v! F/ n# h/ V& |4 felse
7 ~! Q" f7 o( Y/ zResponse.write "不是同一網段"1 a8 ?! }# [* S/ R( l" i* l- U
end if c/ r6 n0 g6 m) n
+ S: `& ~, a; ]1 r# t2 |
[ 本帖最後由 鼕菇蒸雞 於 2006-8-10 20:13 編輯 ] |
|