有時候我們需要判斷某一個IP地址是否屬於一個網段,以決定該用戶能否訪問系統.* N" n. G5 R0 \6 t$ H N
比如用戶登錄的IP是218.6.7.7,而我們的程序必須判斷他是否屬於218.6.0.0/16這個網段(其中/16是新的子網掩碼的表示方式,相當於255.255.0.0).& m, ?5 g7 |$ h) [7 ~
要實現這樣的功能,現在流行的算法是將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開頭的,這將會造成數據溢出而出錯。# m H% C1 a5 e) W) T
其實比較IP是否屬於某一網段,最好的方式就是將IP與網段分別轉為32位二進制,再比較他們的網絡部分是否相同就可以了.asp本身不具備位運行功能,所以要實現這個只有我們手工實現,具體如下:
, |% B2 Y. a# e" d& S'將十進制轉為二進制字符串5 K3 C. `) T0 T' ?/ I, ^
function dec2bin(octNumber)& h4 P3 x( D3 k8 l( o
vara=octNumber# X" I) k; f6 S7 i8 i3 u* t
do
- l P( [' |: W1 N7 h" cdec2bin=cstr(vara mod 2) & dec2bin* @/ Y% f* }8 j, Q) K( b z
vara=vara \ 25 x& X b( Z8 ~- R& b- e
loop until vara=0* K1 i9 O3 h1 |' k" w) e* [
end function
1 s- l! E9 `4 h3 b8 e2 P, z1 U- U; d7 N1 O; j0 M
'將二進制字符串填充為8位1 S5 J v: V: u! w# h
function pad(str)
( S/ M' T0 S7 B6 Mpad=right("00000000" & str,8)- P t2 [$ u8 s" f" x9 D4 C
end function
2 W/ V6 C+ V. a) ~- p" S; A) S4 U
, R3 i+ U+ D; D. V3 D, P'判斷是否是一個IP地址1 d+ l- E$ }$ X4 a- U; H* J
function isIp(ipadd)3 Z, m: W! }! z6 p2 S) f8 F
isIp=false
. h, T9 J/ W4 Dset oReg=new RegExp
% E# `& ~! t# W6 F, e" W# HoReg.IgnoreCase=true
9 u, T0 _# X% k* loReg.global=true
. c- u V7 `! u' I& I, }" I- UoReg.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})"# z" _6 N6 _) W% Y
if oReg.test(ipadd) then isIp=true
0 s( d" s. h& r' Q* R! J3 @set oReg=nothing
; w# D8 w! O- mend function5 `! [6 \2 }% T5 B' x! n' ]9 |/ _
7 B. B) A! ^- o3 {8 Y5 U# M'其中UserIP是我們要檢測的IP
$ d1 g0 b$ y1 J2 R+ O/ f) D'NetIP是要檢測的網段或某個IP,用xxx.xxx.xxx.xxx/N來表示網段,其中N表示子網掩碼位數
! z+ V l$ b0 r( e2 B'注,該程序是環球萬維原創程序,所以如果您要轉載,請保留出處信息,謝謝.+ `, o% r- D k
'程序設計:環球萬維,專業提供域名註冊,虛擬主機服務
J/ S5 e: k( A) y9 [! A5 ~# }. v'網址:http://www.netInter.cn8 ]0 }4 `, b4 _
'以上信息與文章正文是不可分割的一部分,所以如果您要轉載本文章,您必須保留以上信息.( v4 ]! S0 N" q6 G- y( U* N/ A
) y$ h# V" B8 |7 G' v+ [
Function check_ip(UserIp,NetIP)7 B3 A/ V. Z. w+ _- i
currentip=UserIp
; y# \; D U4 i ^1 m! Acollection_ips=split(iplist,",";) '將網絡按點分割成4段& Q* r1 y% T g" `
check_ip=false '初始函數值,false假設IP不在這網段
* z! Z3 Y- v% X. c8 e7 cNetIP=trim(NetIP)
4 K9 y2 A1 I1 S) g" o. r. ^: kslashPos=inStr(NetIP,"/";)
5 i1 f! d- b! zif slashPos=0 then '網段沒含有/符號,他只是一個IP,所以比較比個字符串是否相同就可以了
0 c6 A% v9 I2 h3 [4 Uif NetIP=currentip then, ^; p- ~3 p5 f" O+ b/ S$ f i# E
check_ip=true 'check_ip=true表示IP相等( d3 t; Y7 N, _5 M# ^8 t" J' E
exit function
4 w( {* Y2 Y3 {6 y" N- s6 _( Iend if! l& l4 w* A+ V$ X* \
else
4 _6 R# K6 G7 f& \; w/ g& {/ RnetRang=mid(NetIP,slashPos+1) '得到/後邊的數字% Z: I$ D; ~, N9 p
if not isNumeric(netRang) then '/後邊不是數字,格式不正確
( l5 ~: M- s# f+ Y1 O+ ~exit function
9 i7 g v8 m8 l# Eend if
! [+ X, w0 o7 `& B; }netRang=cint(netRang) '將字符轉為數字
& Q! E: T8 P8 R, @0 oif netRang>31 then
6 N2 G& B/ m) J9 a8 W& oexit function '/後的數字不能超過32位
7 G- J: [5 {9 vend if
: o5 W$ ^6 K* hipsets=split(currentip,".";) '將用戶IP按點分成四段
( p: [. \. k1 c1 _. y( H
1 E6 D; |! q! aC_IP_BIN=pad(dec2bin(ipsets(0))) & pad(dec2bin(ipsets(1))) & pad(dec2bin(ipsets(2))) & pad(dec2bin(ipsets(3)))
4 |' {+ N% m2 E& p# O) L' b'上邊這行是將用戶IP地址手工轉換為對應的一個32個字符長的二進制) W8 e6 K0 V- y8 J# z' p( s
ipsets=split(NetIP,".") '按上邊的過程將網段IP同樣轉為32個字符長的二進制
, }$ o: b2 `+ @* usPos=instr(ipsets(3),"/") '最後一點格式應該是 數字/數字) t: u- Q0 u# a
if sPos=0 then1 A6 v6 E+ i/ |, z* t
exit function. l1 i" j/ t/ x) p
end if# |( U' X, q! q0 g! A
ipsets(3)=left(ipsets(3),sPos-1) '得到最後一段/前邊的數字9 ?. f5 A; h6 T; t$ }
S_IP_BIN=pad(dec2bin(ipsets(0))) & pad(dec2bin(ipsets(1))) & pad(dec2bin(ipsets(2))) & pad(dec2bin(ipsets(3)))
* i4 l4 u8 |# o; J) y4 K. v'將其轉換為32個字符長的二進制6 s6 J: C6 N7 e* Z
if left(C_IP_BIN,netRang) = left(S_IP_BIN,netRang) then '比較網段絡是否相同就可以判斷用戶IP否屬於某個網段了5 z/ g# t; _* H. S. f1 s8 V% d
check_ip=true$ L: C; f1 M+ a( \: J; F, d$ f
end if2 |" ?4 y9 t) q' l$ H L! g R
end if
# x$ y e' l0 q3 c: j+ g* e* D7 Qend function
+ r* C8 y6 R, C
) B) n( n# ~$ Z1 ]- G應用舉例:% j9 N |" e! U! W2 N
4 L0 s9 ~$ Y: }% @要判斷61.139.1.1是否在61.139.0.0/16 (255.255.0.0)這個網段
$ ~2 q: D+ z8 e7 h8 V只需要簡單的使用這個函數就可以了,如:
$ I6 n5 r$ L5 @, {2 z% e3 b9 h; o* w) H9 r! u, z
if check_ip("61.139.1.1","61.139.0.0/16") then5 k9 X8 k( F7 J0 t7 g
Response.write "同一網段"; ]* [8 i1 H) g9 p( ?& \! g3 S$ Y
else, M" o {( h0 P9 n0 K- N' d' P
Response.write "不是同一網段"4 O9 |5 A* ` o
end if
) O3 N9 k5 M5 h$ d: `! N0 ?% E" V, [9 X+ d/ y0 g. p) l0 @6 G
[ 本帖最後由 鼕菇蒸雞 於 2006-8-10 20:13 編輯 ] |
|