有時候我們需要判斷某一個IP地址是否屬於一個網段,以決定該用戶能否訪問系統.: x8 I% K* T- |) T' n: H9 G
比如用戶登錄的IP是218.6.7.7,而我們的程序必須判斷他是否屬於218.6.0.0/16這個網段(其中/16是新的子網掩碼的表示方式,相當於255.255.0.0).
( m+ L6 D# U" Z( q9 V要實現這樣的功能,現在流行的算法是將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開頭的,這將會造成數據溢出而出錯。% h. A3 c" q) S7 o! V2 G
其實比較IP是否屬於某一網段,最好的方式就是將IP與網段分別轉為32位二進制,再比較他們的網絡部分是否相同就可以了.asp本身不具備位運行功能,所以要實現這個只有我們手工實現,具體如下:
: S# h! m* S' E; q'將十進制轉為二進制字符串1 J( K$ L1 \( g; v& p
function dec2bin(octNumber)
. z( T* x! l. }" l+ v: [! A7 vvara=octNumber) }' T* X* Z# j* E3 [. ]: ?; t
do 1 }5 v4 ], Z" u; H7 @' w0 G
dec2bin=cstr(vara mod 2) & dec2bin0 @) K: I! j1 z$ e0 G* }
vara=vara \ 2# P7 u& @9 A2 a# i9 b- V8 [$ @
loop until vara=0
+ Q" }( u/ r/ V7 |- y8 nend function
0 Z9 x6 n3 s9 t2 F& o' ]5 b2 N& R0 M) {* z
'將二進制字符串填充為8位; ~) I" p2 Z4 i6 y( h
function pad(str)
. |$ }* O& O5 ~* x8 a$ fpad=right("00000000" & str,8)
: p; Q L5 g6 d6 X+ m" g0 yend function% g4 S; `% {" s
* v; v% }) C$ [6 ^4 a- [5 O'判斷是否是一個IP地址1 f" n7 r, \! v% F7 J8 G. F
function isIp(ipadd), ~3 K2 O& L4 I- k% g5 K
isIp=false g; [8 c) P6 O; z+ d5 N8 x$ u
set oReg=new RegExp7 g1 l0 o% Y# T) w
oReg.IgnoreCase=true: t1 d' u( ~9 Y9 M
oReg.global=true
: n7 F+ J1 ~+ k3 p1 m& r( _, x2 R4 moReg.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})"8 r# y/ H6 K2 D" l# H
if oReg.test(ipadd) then isIp=true7 s6 H! c$ ]$ t. b. ]
set oReg=nothing1 m7 j3 K9 ~+ v$ Y9 `# A& P1 Z
end function
- F1 O# p2 M' s. s$ B8 ?& |0 z) [, e7 r7 N6 M" g z- e( B( W
'其中UserIP是我們要檢測的IP
m8 C. f/ D# l# q0 L: L'NetIP是要檢測的網段或某個IP,用xxx.xxx.xxx.xxx/N來表示網段,其中N表示子網掩碼位數 9 S& N9 k* ?; [$ E v9 }
'注,該程序是環球萬維原創程序,所以如果您要轉載,請保留出處信息,謝謝.
, ?, b+ `8 t, Q: G3 T'程序設計:環球萬維,專業提供域名註冊,虛擬主機服務
$ E& ]) ~( L7 i& n' N'網址:http://www.netInter.cn
2 ~" R: J- y) J* ?9 V u4 @'以上信息與文章正文是不可分割的一部分,所以如果您要轉載本文章,您必須保留以上信息.9 C" d0 _5 V* u, |- y
) |3 e; A7 k# J+ |' ?% [Function check_ip(UserIp,NetIP)
. @8 M0 M! o* x. `; b8 A5 Ocurrentip=UserIp# c+ t& O( _! I
collection_ips=split(iplist,",";) '將網絡按點分割成4段
% i/ t! d- x; F/ q& e: b& r0 x7 bcheck_ip=false '初始函數值,false假設IP不在這網段, R9 |" a9 A+ M% v
NetIP=trim(NetIP)
$ Y7 s7 ^" \% Y- SslashPos=inStr(NetIP,"/";)& @. S+ N+ e6 A- `+ L
if slashPos=0 then '網段沒含有/符號,他只是一個IP,所以比較比個字符串是否相同就可以了
) P: _6 D# G0 } Tif NetIP=currentip then0 E$ P0 A! T7 g" I
check_ip=true 'check_ip=true表示IP相等8 v5 r) l. [% V7 Y* S
exit function
2 z0 D* k5 U# qend if: ]( I7 u0 l1 a# L7 B0 u
else. q# {2 o: j7 e( p) q
netRang=mid(NetIP,slashPos+1) '得到/後邊的數字. x3 _- w7 f& I# l! V* `" I
if not isNumeric(netRang) then '/後邊不是數字,格式不正確
1 ?, c2 c$ P5 b/ rexit function9 P) x: J$ a& i! \/ a+ [; i
end if
0 e( }8 D. T1 M9 p9 F6 D8 l) fnetRang=cint(netRang) '將字符轉為數字* c5 Q( c. I2 |0 X8 U! j
if netRang>31 then" [. H% k4 S. c+ Y0 Z! V% i: l
exit function '/後的數字不能超過32位
) T: i) J6 y A! B% `* wend if
; m" O ]9 b5 k8 Z) E- qipsets=split(currentip,".";) '將用戶IP按點分成四段
, y/ ~: y+ m* Z
+ j) X5 e. \: {; V" ~8 \3 Y/ @C_IP_BIN=pad(dec2bin(ipsets(0))) & pad(dec2bin(ipsets(1))) & pad(dec2bin(ipsets(2))) & pad(dec2bin(ipsets(3)))
; g0 f( A' [# f$ e$ B" }; k+ H& m7 s'上邊這行是將用戶IP地址手工轉換為對應的一個32個字符長的二進制
u$ A1 N! E$ R, Dipsets=split(NetIP,".") '按上邊的過程將網段IP同樣轉為32個字符長的二進制, }/ Q0 ` ^' X' Z ~. k* _, Z( l' d
sPos=instr(ipsets(3),"/") '最後一點格式應該是 數字/數字
/ F) d @0 \0 P4 p: j L. ~if sPos=0 then; o( m r; @" N6 F
exit function) `% [' [8 ^; r! k3 Z2 R
end if: s' V# B) q5 R1 j1 z3 x
ipsets(3)=left(ipsets(3),sPos-1) '得到最後一段/前邊的數字
" T: A4 l) ] VS_IP_BIN=pad(dec2bin(ipsets(0))) & pad(dec2bin(ipsets(1))) & pad(dec2bin(ipsets(2))) & pad(dec2bin(ipsets(3))) B! b/ A; I- X$ U5 H7 B
'將其轉換為32個字符長的二進制8 J( \: D" M% Q+ P. Z# Z
if left(C_IP_BIN,netRang) = left(S_IP_BIN,netRang) then '比較網段絡是否相同就可以判斷用戶IP否屬於某個網段了$ \# _1 E% @$ j5 L: i/ Z
check_ip=true
" e1 p" Z' x$ Y' l0 ?- {8 uend if/ e: t6 h: W+ Y
end if
2 ^. I0 O: ~) y& m, m% s9 Lend function" {7 j& I! a. g' T- e6 h0 `
1 N2 g3 l" j. H& a, X5 X" m
應用舉例:8 }* Y1 d6 k! _! a7 [ P
% [- C& ^5 d1 @$ Y
要判斷61.139.1.1是否在61.139.0.0/16 (255.255.0.0)這個網段
+ x' l% P1 l# v% t只需要簡單的使用這個函數就可以了,如:- d; q9 h1 q2 W. y9 v2 j
" x9 u* A2 X/ j0 F, `
if check_ip("61.139.1.1","61.139.0.0/16") then% a# i# b" u! J J, T
Response.write "同一網段"% L- r# h! v; k& y/ O6 j2 q# ?
else4 d4 D0 q/ t# x: y
Response.write "不是同一網段": q; r+ i! I6 a0 N0 j Z) `4 O# q. L9 ~
end if
3 i: B) Z9 {8 M9 U; h
- K& X3 n5 F6 ?3 O[ 本帖最後由 鼕菇蒸雞 於 2006-8-10 20:13 編輯 ] |
|