1
using
System;
2
using
System.Collections.Generic;
3
using
System.Text;
4
using
System.IO;
5
using
System.Text.RegularExpressions;
6
using
System.Net;
7
using
System.Net.Sockets;
8
9
namespace
AjaxIP
10
{
11
public
class
IPLocation
12
{
13
public
string
IP {
get
;
set
; }
14
public
string
Country {
get
;
set
; }
15
public
string
Local {
get
;
set
; }
16
}
17
18
public
class
QQWryLocator
19
{
20
static
Encoding encoding
=
Encoding.GetEncoding(
"
GB2312
"
);
21
22
private
byte
[] data;
23
int
firstStartIpOffset;
24
int
lastStartIpOffset;
25
int
ipCount;
26
27
public
int
Count {
get
{
return
ipCount; } }
28
29
public
QQWryLocator(
string
dataPath)
30
{
31
using
(FileStream fs
=
new
FileStream(dataPath, FileMode.Open, FileAccess.Read, FileShare.Read))
32
{
33
data
=
new
byte
[fs.Length];
34
fs.Read(data,
0
, data.Length);
35
}
36
37
firstStartIpOffset
=
(
int
)data[
0
]
+
(((
int
)data[
1
])
<<
8
)
+
(((
int
)data[
2
])
<<
16
)
+
(((
int
)data[
3
])
<<
24
);
38
lastStartIpOffset
=
(
int
)data[
4
]
+
(((
int
)data[
5
])
<<
8
)
+
(((
int
)data[
6
])
<<
16
)
+
(((
int
)data[
7
])
<<
24
);
39
ipCount
=
(lastStartIpOffset
-
firstStartIpOffset)
/
7
+
1
;
40
41
if
(ipCount
<=
1
)
42
{
43
throw
new
ArgumentException(
"
ip FileDataError
"
);
44
}
45
}
46
47
public
static
uint
IpToInt(
string
ip)
48
{
49
//
string[] strArray = ip.Split('.');
50
//
return (uint.Parse(strArray[0]) << 24) + (uint.Parse(strArray[1]) << 16) + (uint.Parse(strArray[2]) << 8) + uint.Parse(strArray[0]);
51
//
return (uint)IPAddress.HostToNetworkOrder((int)(IPAddress.Parse(ip).Address));
52
53
byte
[] bytes
=
IPAddress.Parse(ip).GetAddressBytes();
54
return
(
uint
)bytes[
3
]
+
(((
uint
)bytes[
2
])
<<
8
)
+
(((
uint
)bytes[
1
])
<<
16
)
+
(((
uint
)bytes[
0
])
<<
24
);
55
}
56
57
public
static
string
IntToIP(
uint
ip_Int)
58
{
59
return
new
IPAddress(ip_Int).ToString();
60
}
61
62
public
IPLocation Query(
string
ip)
63
{
64
IPAddress address
=
IPAddress.Parse(ip);
65
if
(address.AddressFamily
!=
AddressFamily.InterNetwork)
66
{
67
throw
new
ArgumentException(
"
不支持非IPV4的地址
"
);
68
}
69
70
if
(IPAddress.IsLoopback(address))
71
{
72
return
new
IPLocation() { IP
=
ip, Country
=
"
本机内部环回地址
"
, Local
=
string
.Empty };
73
}
74
75
uint
intIP
=
(
uint
)IPAddress.HostToNetworkOrder((
int
)address.Address);
76
77
//
if ((((intIP >= IpToInt("0.0.0.0")) && (intIP <= IpToInt("2.255.255.255"))) || ((intIP >= IpToInt("64.0.0.0")) && (intIP <= IpToInt("126.255.255.255")))) ||
78
//
((intIP >= IpToInt("58.0.0.0")) && (intIP <= IpToInt("60.255.255.255"))))
79
//
if (intIP <= 50331647 || (intIP >= 1073741824 && intIP <= 2130706431) || (intIP >= 973078528 && intIP <= 1023410175))
80
//
{
81
//
return new IPLocation() { IP = ip, Country = "网络保留地址", Local = string.Empty };
82
//
}
83
84
IPLocation ipLocation
=
new
IPLocation() { IP
=
ip };
85
86
uint
right
=
(
uint
)ipCount;
87
uint
left
=
0
;
88
uint
middle
=
0
;
89
uint
startIp
=
0
;
90
uint
endIpOff
=
0
;
91
uint
endIp
=
0
;
92
int
countryFlag
=
0
;
93
94
while
(left
<
(right
-
1
))
95
{
96
middle
=
(right
+
left)
/
2
;
97
startIp
=
GetStartIp(middle,
out
endIpOff);
98
if
(intIP
==
startIp)
99
{
100
left
=
middle;
101
break
;
102
}
103
if
(intIP
>
startIp)
104
{
105
left
=
middle;
106
}
107
else
108
{
109
right
=
middle;
110
}
111
}
112
startIp
=
GetStartIp(left,
out
endIpOff);
113
endIp
=
GetEndIp(endIpOff,
out
countryFlag);
114
if
((startIp
<=
intIP)
&&
(endIp
>=
intIP))
115
{
116
string
local;
117
ipLocation.Country
=
GetCountry(endIpOff, countryFlag,
out
local);
118
ipLocation.Local
=
local;
119
}
120
else
121
{
122
ipLocation.Country
=
"
未知
"
;
123
ipLocation.Local
=
string
.Empty;
124
}
125
return
ipLocation;
126
}
127
128
private
uint
GetStartIp(
uint
left,
out
uint
endIpOff)
129
{
130
int
leftOffset
=
(
int
)(firstStartIpOffset
+
(left
*
7
));
131
endIpOff
=
(
uint
)data[
4
+
leftOffset]
+
(((
uint
)data[
5
+
leftOffset])
<<
8
)
+
(((
uint
)data[
6
+
leftOffset])
<<
16
);
132
return
(
uint
)data[leftOffset]
+
(((
uint
)data[
1
+
leftOffset])
<<
8
)
+
(((
uint
)data[
2
+
leftOffset])
<<
16
)
+
(((
uint
)data[
3
+
leftOffset])
<<
24
);
133
}
134
135
private
uint
GetEndIp(
uint
endIpOff,
out
int
countryFlag)
136
{
137
countryFlag
=
data[
4
+
endIpOff];
138
return
(
uint
)data[endIpOff]
+
(((
uint
)data[
1
+
endIpOff])
<<
8
)
+
(((
uint
)data[
2
+
endIpOff])
<<
16
)
+
(((
uint
)data[
3
+
endIpOff])
<<
24
);
139
}
140
141
///
<summary>
142
///
Gets the country.
143
///
</summary>
144
///
<param name="endIpOff">
The end ip off.
</param>
145
///
<param name="countryFlag">
The country flag.
</param>
146
///
<param name="local">
The local.
</param>
147
///
<returns>
country
</returns>
148
private
string
GetCountry(
uint
endIpOff,
int
countryFlag,
out
string
local)
149
{
150
string
country
=
string
.Empty;
151
uint
offset
=
endIpOff
+
4
;
152
switch
(countryFlag)
153
{
154
case
1
:
155
case
2
:
156
country
=
GetFlagStr(
ref
offset,
ref
countryFlag,
ref
endIpOff);
157
offset
=
endIpOff
+
8
;
158
local
=
(
1
==
countryFlag)
?
string
.Empty : GetFlagStr(
ref
offset,
ref
countryFlag,
ref
endIpOff);
159
break
;
160
default
:
161
country
=
GetFlagStr(
ref
offset,
ref
countryFlag,
ref
endIpOff);
162
local
=
GetFlagStr(
ref
offset,
ref
countryFlag,
ref
endIpOff);
163
break
;
164
}
165
return
country;
166
}
167
168
private
string
GetFlagStr(
ref
uint
offset,
ref
int
countryFlag,
ref
uint
endIpOff)
169
{
170
int
flag
=
0
;
171
while
(
true
)
172
{
173
flag
=
data[offset];
174
//
没有重定向
175
if
(flag
!=
1
&&
flag
!=
2
)
176
{
177
break
;
178
}
179
if
(flag
==
2
)
180
{
181
countryFlag
=
2
;
182
endIpOff
=
offset
-
4
;
183
}
184
offset
=
(
uint
)data[
1
+
offset]
+
(((
uint
)data[
2
+
offset])
<<
8
)
+
(((
uint
)data[
3
+
offset])
<<
16
);
185
}
186
if
(offset
<
12
)
187
{
188
return
string
.Empty;
189
}
190
return
GetStr(
ref
offset);
191
}
192
193
///
<summary>
194
///
读取字符串...
195
///
</summary>
196
///
<param name="offset"></param>
197
///
<returns></returns>
198
private
string
GetStr(
ref
uint
offset)
199
{
200
byte
lowByte
=
0
;
201
byte
highByte
=
0
;
202
StringBuilder stringBuilder
=
new
StringBuilder(
16
);
203
while
(
true
)
204
{
205
lowByte
=
data[offset
++
];
206
if
(lowByte
==
0
)
207
{
208
return
stringBuilder.ToString();
209
}
210
211
if
(lowByte
>
0x7f
)
212
{
213
highByte
=
data[offset
++
];
214
if
(highByte
==
0
)
215
{
216
return
stringBuilder.ToString();
217
}
218
stringBuilder.Append(encoding.GetString(
new
byte
[] { lowByte, highByte }));
219
}
220
else
221
{
222
stringBuilder.Append((
char
)lowByte);
223
}
224
}
225
}
226
}
227
}