根据LumaQQ改写而成.
1
using System;
2
using System.IO;
3
using System.Text;
4
5
namespace BDQQ.Data
6
{
7
/// <summary>
8
/// QQWry 的摘要说明。
9
/// </summary>
10
public class QQWry
11
{
12
#region 第一种模式
13
/// <summary>
14
/// 第一种模式
15
/// </summary>
16
#endregion
17
private const byte REDIRECT_MODE_1 = 0x01;
18
19
#region 第二种模式
20
/// <summary>
21
/// 第二种模式
22
/// </summary>
23
#endregion
24
private const byte REDIRECT_MODE_2 = 0x02;
25
26
#region 每条记录长度
27
/// <summary>
28
/// 每条记录长度
29
/// </summary>
30
#endregion
31
private const int IP_RECORD_LENGTH = 7;
32
33
#region 数据库文件
34
/// <summary>
35
/// 文件对象
36
/// </summary>
37
#endregion
38
private FileStream ipFile;
39
40
private const string unCountry = "未知国家";
41
private const string unArea = "未知地区";
42
43
#region 索引开始位置
44
/// <summary>
45
/// 索引开始位置
46
/// </summary>
47
#endregion
48
private long ipBegin;
49
50
#region 索引结束位置
51
/// <summary>
52
/// 索引结束位置
53
/// </summary>
54
#endregion
55
private long ipEnd;
56
57
#region IP地址对象
58
/// <summary>
59
/// IP对象
60
/// </summary>
61
#endregion
62
private IPLocation loc;
63
64
#region 存储文本内容
65
/// <summary>
66
/// 存储文本内容
67
/// </summary>
68
#endregion
69
private byte[] buf;
70
71
#region 存储3字节
72
/// <summary>
73
/// 存储3字节
74
/// </summary>
75
#endregion
76
private byte[] b3;
77
78
#region 存储4字节
79
/// <summary>
80
/// 存储4字节IP地址
81
/// </summary>
82
#endregion
83
private byte[] b4;
84
85
#region 构造函数
86
/// <summary>
87
/// 构造函数
88
/// </summary>
89
/// <param name="ipfile">IP数据库文件绝对路径</param>
90
#endregion
91
public QQWry( string ipfile )
92
{
93
buf = new byte[100];
94
b3 = new byte[3];
95
b4 = new byte[4];
96
try
97
{
98
ipFile = new FileStream( ipfile,FileMode.Open );
99
}
100
catch( Exception ex )
101
{
102
throw new Exception( ex.Message );
103
}
104
ipBegin = readLong4(0);
105
ipEnd = readLong4(4);
106
loc = new IPLocation();
107
}
108
109
110
#region 根据IP地址搜索
111
/// <summary>
112
/// 搜索IP地址搜索
113
/// </summary>
114
/// <param name="ip"></param>
115
/// <returns></returns>
116
#endregion
117
public IPLocation SearchIPLocation( string ip )
118
{
119
//将字符IP转换为字节
120
string[] ipSp = ip.Split('.');
121
if( ipSp.Length != 4 )
122
{
123
throw new ArgumentOutOfRangeException( "不是合法的IP地址!" );
124
}
125
byte[] IP = new byte[4];
126
for( int i = 0; i < IP.Length ; i++ )
127
{
128
IP[i] = (byte)(Int32.Parse( ipSp[i] ) & 0xFF) ;
129
}
130
131
IPLocation local = null;
132
long offset = locateIP( IP );
133
134
if( offset != -1 )
135
{
136
local = getIPLocation( offset );
137
}
138
139
if( local == null )
140
{
141
local = new IPLocation();
142
local.area = unArea;
143
local.country = unCountry;
144
}
145
return local;
146
}
147
148
149
#region 取得具体信息
150
/// <summary>
151
/// 取得具体信息
152
/// </summary>
153
/// <param name="offset"></param>
154
/// <returns></returns>
155
#endregion
156
private IPLocation getIPLocation( long offset )
157
{
158
ipFile.Position = offset + 4;
159
//读取第一个字节判断是否是标志字节
160
byte one = (byte)ipFile.ReadByte();
161
if( one == REDIRECT_MODE_1 )
162
{
163
//第一种模式
164
//读取国家偏移
165
long countryOffset = readLong3();
166
//转至偏移处
167
ipFile.Position = countryOffset;
168
//再次检查标志字节
169
byte b = (byte)ipFile.ReadByte();
170
if( b == REDIRECT_MODE_2 )
171
{
172
loc.country = readString( readLong3() );
173
ipFile.Position = countryOffset + 4;
174
}
175
else
176
loc.country = readString( countryOffset );
177
178
//读取地区标志
179
loc.area = readArea( ipFile.Position );
180
181
}
182
else if( one == REDIRECT_MODE_2 )
183
{
184
//第二种模式
185
loc.country = readString( readLong3() );
186
loc.area = readArea( offset + 8 );
187
}
188
else
189
{
190
//普通模式
191
loc.country = readString( --ipFile.Position );
192
loc.area = readString( ipFile.Position );
193
}
194
return loc;
195
}
196
197
198
#region 取得地区信息
199
/// <summary>
200
/// 读取地区名称
201
/// </summary>
202
/// <param name="offset"></param>
203
/// <returns></returns>
204
#endregion
205
private string readArea( long offset )
206
{
207
ipFile.Position = offset;
208
byte one = (byte)ipFile.ReadByte();
209
if( one == REDIRECT_MODE_1 || one == REDIRECT_MODE_2 )
210
{
211
long areaOffset = readLong3( offset + 1 );
212
if( areaOffset == 0 )
213
return unArea;
214
else
215
{
216
return readString( areaOffset );
217
}
218
}
219
else
220
{
221
return readString( offset );
222
}
223
}
224
225
226
#region 读取字符串
227
/// <summary>
228
/// 读取字符串
229
/// </summary>
230
/// <param name="offset"></param>
231
/// <returns></returns>
232
#endregion
233
private string readString( long offset )
234
{
235
ipFile.Position = offset;
236
int i = 0;
237
for(i = 0, buf[i]=(byte)ipFile.ReadByte();buf[i] != (byte)(0);buf[++i]=(byte)ipFile.ReadByte());
238
239
if( i > 0 )
240
return Encoding.Default.GetString( buf,0,i );
241
else
242
return "";
243
}
244
245
246
#region 查找IP地址所在的绝对偏移量
247
/// <summary>
248
/// 查找IP地址所在的绝对偏移量
249
/// </summary>
250
/// <param name="ip"></param>
251
/// <returns></returns>
252
#endregion
253
private long locateIP( byte[] ip )
254
{
255
long m = 0;
256
int r;
257
258
//比较第一个IP项
259
readIP( ipBegin, b4 );
260
r = compareIP( ip,b4);
261
if( r == 0 )
262
return ipBegin;
263
else if( r < 0 )
264
return -1;
265
//开始二分搜索
266
for( long i = ipBegin,j=ipEnd; i<j; )
267
{
268
m = this.getMiddleOffset( i,j );
269
readIP( m,b4 );
270
r = compareIP( ip,b4 );
271
if( r > 0 )
272
i = m;
273
else if( r < 0 )
274
{
275
if( m == j )
276
{
277
j -= IP_RECORD_LENGTH;
278
m = j;
279
}
280
else
281
{
282
j = m;
283
}
284
}
285
else
286
return readLong3( m+4 );
287
}
288
m = readLong3( m+4 );
289
readIP( m,b4 );
290
r = compareIP( ip,b4 );
291
if( r <= 0 )
292
return m;
293
else
294
return -1;
295
}
296
297
298
#region 读出4字节的IP地址
299
/// <summary>
300
/// 从当前位置读取四字节,此四字节是IP地址
301
/// </summary>
302
/// <param name="offset"></param>
303
/// <param name="ip"></param>
304
#endregion
305
private void readIP( long offset, byte[] ip )
306
{
307
ipFile.Position = offset;
308
ipFile.Read( ip,0,ip.Length );
309
byte tmp = ip[0];
310
ip[0] = ip[3];
311
ip[3] = tmp;
312
tmp = ip[1];
313
ip[1] = ip[2];
314
ip[2] = tmp;
315
}
316
317
318
#region 比较IP地址是否相同
319
/// <summary>
320
/// 比较IP地址是否相同
321
/// </summary>
322
/// <param name="ip"></param>
323
/// <param name="beginIP"></param>
324
/// <returns>0:相等,1:ip大于beginIP,-1:小于</returns>
325
#endregion
326
private int compareIP( byte[] ip, byte[] beginIP )
327
{
328
for( int i = 0; i < 4; i++ )
329
{
330
int r = compareByte( ip[i],beginIP[i] );
331
if( r != 0 )
332
return r;
333
}
334
return 0;
335
}
336
337
338
#region 比较两个字节是否相等
339
/// <summary>
340
/// 比较两个字节是否相等
341
/// </summary>
342
/// <param name="bsrc"></param>
343
/// <param name="bdst"></param>
344
/// <returns></returns>
345
#endregion
346
private int compareByte( byte bsrc, byte bdst )
347
{
348
if( ( bsrc&0xFF ) > ( bdst&0xFF ) )
349
return 1;
350
else if( (bsrc ^ bdst) == 0 )
351
return 0;
352
else
353
return -1;
354
}
355
356
357
#region 根据当前位置读取4字节
358
/// <summary>
359
/// 从当前位置读取4字节,转换为长整型
360
/// </summary>
361
/// <param name="offset"></param>
362
/// <returns></returns>
363
#endregion
364
private long readLong4( long offset )
365
{
366
long ret = 0;
367
ipFile.Position = offset;
368
ret |= ( ipFile.ReadByte() & 0xFF );
369
ret |= ( ( ipFile.ReadByte() << 8 ) & 0xFF00 );
370
ret |= ( ( ipFile.ReadByte() << 16 ) & 0xFF0000 );
371
ret |= ( ( ipFile.ReadByte() << 24 ) & 0xFF000000 );
372
return ret;
373
}
374
375
376
#region 根据当前位置,读取3字节
377
/// <summary>
378
/// 根据当前位置,读取3字节
379
/// </summary>
380
/// <param name="offset"></param>
381
/// <returns></returns>
382
#endregion
383
private long readLong3( long offset )
384
{
385
long ret = 0;
386
ipFile.Position = offset;
387
ret |= ( ipFile.ReadByte() & 0xFF );
388
ret |= ( (ipFile.ReadByte() << 8 ) & 0xFF00 );
389
ret |= ( (ipFile.ReadByte() << 16 ) & 0xFF0000 );
390
return ret;
391
}
392
393
394
#region 从当前位置读取3字节
395
/// <summary>
396
/// 从当前位置读取3字节
397
/// </summary>
398
/// <returns></returns>
399
#endregion
400
private long readLong3()
401
{
402
long ret = 0;
403
ret |= ( ipFile.ReadByte() & 0xFF );
404
ret |= ( (ipFile.ReadByte() << 8 ) & 0xFF00 );
405
ret |= ( (ipFile.ReadByte() << 16 ) & 0xFF0000 );
406
return ret;
407
}
408
409
410
#region 取得begin和end之间的偏移量
411
/// <summary>
412
/// 取得begin和end中间的偏移
413
/// </summary>
414
/// <param name="begin"></param>
415
/// <param name="end"></param>
416
/// <returns></returns>
417
#endregion
418
private long getMiddleOffset( long begin, long end )
419
{
420
long records = ( end - begin ) / IP_RECORD_LENGTH;
421
records >>= 1;
422
if( records == 0 )
423
records = 1;
424
return begin + records * IP_RECORD_LENGTH;
425
}
426
} //class QQWry
427
428
public class IPLocation
429
{
430
public String country;
431
public String area;
432
433
public IPLocation()
434
{
435
country = area = "";
436
}
437
438
public IPLocation getCopy()
439
{
440
IPLocation ret = new IPLocation();
441
ret.country = country;
442
ret.area = area;
443
return ret;
444
}
445
}
446
}
447
1
using System;2
using System.IO;3
using System.Text;4

5
namespace BDQQ.Data6
{7
/// <summary>8
/// QQWry 的摘要说明。9
/// </summary>10
public class QQWry11
{12
#region 第一种模式13
/// <summary>14
/// 第一种模式15
/// </summary>16
#endregion17
private const byte REDIRECT_MODE_1 = 0x01;18

19
#region 第二种模式20
/// <summary>21
/// 第二种模式22
/// </summary>23
#endregion24
private const byte REDIRECT_MODE_2 = 0x02;25

26
#region 每条记录长度27
/// <summary>28
/// 每条记录长度29
/// </summary>30
#endregion 31
private const int IP_RECORD_LENGTH = 7;32

33
#region 数据库文件34
/// <summary>35
/// 文件对象36
/// </summary>37
#endregion 38
private FileStream ipFile;39

40
private const string unCountry = "未知国家";41
private const string unArea = "未知地区";42

43
#region 索引开始位置44
/// <summary>45
/// 索引开始位置46
/// </summary>47
#endregion48
private long ipBegin;49

50
#region 索引结束位置51
/// <summary>52
/// 索引结束位置53
/// </summary>54
#endregion55
private long ipEnd;56

57
#region IP地址对象58
/// <summary>59
/// IP对象60
/// </summary>61
#endregion62
private IPLocation loc;63

64
#region 存储文本内容65
/// <summary>66
/// 存储文本内容67
/// </summary>68
#endregion69
private byte[] buf;70

71
#region 存储3字节72
/// <summary>73
/// 存储3字节74
/// </summary>75
#endregion76
private byte[] b3;77

78
#region 存储4字节79
/// <summary>80
/// 存储4字节IP地址81
/// </summary>82
#endregion83
private byte[] b4;84

85
#region 构造函数86
/// <summary>87
/// 构造函数88
/// </summary>89
/// <param name="ipfile">IP数据库文件绝对路径</param>90
#endregion91
public QQWry( string ipfile )92
{ 93
buf = new byte[100];94
b3 = new byte[3];95
b4 = new byte[4]; 96
try97
{98
ipFile = new FileStream( ipfile,FileMode.Open );99
}100
catch( Exception ex )101
{102
throw new Exception( ex.Message );103
} 104
ipBegin = readLong4(0);105
ipEnd = readLong4(4);106
loc = new IPLocation();107
}108

109

110
#region 根据IP地址搜索111
/// <summary>112
/// 搜索IP地址搜索113
/// </summary>114
/// <param name="ip"></param>115
/// <returns></returns>116
#endregion117
public IPLocation SearchIPLocation( string ip )118
{119
//将字符IP转换为字节120
string[] ipSp = ip.Split('.');121
if( ipSp.Length != 4 )122
{123
throw new ArgumentOutOfRangeException( "不是合法的IP地址!" );124
}125
byte[] IP = new byte[4];126
for( int i = 0; i < IP.Length ; i++ )127
{128
IP[i] = (byte)(Int32.Parse( ipSp[i] ) & 0xFF) ;129
}130

131
IPLocation local = null;132
long offset = locateIP( IP );133

134
if( offset != -1 )135
{136
local = getIPLocation( offset );137
}138

139
if( local == null )140
{141
local = new IPLocation();142
local.area = unArea;143
local.country = unCountry;144
}145
return local;146
}147

148

149
#region 取得具体信息150
/// <summary>151
/// 取得具体信息152
/// </summary>153
/// <param name="offset"></param>154
/// <returns></returns>155
#endregion156
private IPLocation getIPLocation( long offset )157
{158
ipFile.Position = offset + 4;159
//读取第一个字节判断是否是标志字节160
byte one = (byte)ipFile.ReadByte();161
if( one == REDIRECT_MODE_1 )162
{163
//第一种模式164
//读取国家偏移165
long countryOffset = readLong3();166
//转至偏移处167
ipFile.Position = countryOffset;168
//再次检查标志字节169
byte b = (byte)ipFile.ReadByte();170
if( b == REDIRECT_MODE_2 )171
{172
loc.country = readString( readLong3() );173
ipFile.Position = countryOffset + 4;174
}175
else176
loc.country = readString( countryOffset );177

178
//读取地区标志179
loc.area = readArea( ipFile.Position );180

181
}182
else if( one == REDIRECT_MODE_2 )183
{184
//第二种模式185
loc.country = readString( readLong3() );186
loc.area = readArea( offset + 8 );187
}188
else189
{190
//普通模式191
loc.country = readString( --ipFile.Position );192
loc.area = readString( ipFile.Position );193
}194
return loc;195
}196

197

198
#region 取得地区信息199
/// <summary>200
/// 读取地区名称201
/// </summary>202
/// <param name="offset"></param>203
/// <returns></returns>204
#endregion205
private string readArea( long offset )206
{207
ipFile.Position = offset;208
byte one = (byte)ipFile.ReadByte();209
if( one == REDIRECT_MODE_1 || one == REDIRECT_MODE_2 )210
{211
long areaOffset = readLong3( offset + 1 );212
if( areaOffset == 0 )213
return unArea;214
else215
{216
return readString( areaOffset );217
}218
}219
else220
{221
return readString( offset );222
}223
}224

225

226
#region 读取字符串227
/// <summary>228
/// 读取字符串229
/// </summary>230
/// <param name="offset"></param>231
/// <returns></returns>232
#endregion233
private string readString( long offset )234
{235
ipFile.Position = offset;236
int i = 0;237
for(i = 0, buf[i]=(byte)ipFile.ReadByte();buf[i] != (byte)(0);buf[++i]=(byte)ipFile.ReadByte());238
239
if( i > 0 )240
return Encoding.Default.GetString( buf,0,i );241
else242
return "";243
}244

245

246
#region 查找IP地址所在的绝对偏移量247
/// <summary>248
/// 查找IP地址所在的绝对偏移量249
/// </summary>250
/// <param name="ip"></param>251
/// <returns></returns>252
#endregion253
private long locateIP( byte[] ip )254
{255
long m = 0;256
int r;257

258
//比较第一个IP项259
readIP( ipBegin, b4 );260
r = compareIP( ip,b4);261
if( r == 0 )262
return ipBegin;263
else if( r < 0 )264
return -1;265
//开始二分搜索266
for( long i = ipBegin,j=ipEnd; i<j; )267
{268
m = this.getMiddleOffset( i,j );269
readIP( m,b4 );270
r = compareIP( ip,b4 );271
if( r > 0 )272
i = m;273
else if( r < 0 )274
{275
if( m == j )276
{277
j -= IP_RECORD_LENGTH;278
m = j;279
}280
else281
{282
j = m;283
}284
}285
else286
return readLong3( m+4 );287
}288
m = readLong3( m+4 );289
readIP( m,b4 );290
r = compareIP( ip,b4 );291
if( r <= 0 )292
return m;293
else294
return -1;295
}296

297

298
#region 读出4字节的IP地址299
/// <summary>300
/// 从当前位置读取四字节,此四字节是IP地址301
/// </summary>302
/// <param name="offset"></param>303
/// <param name="ip"></param>304
#endregion305
private void readIP( long offset, byte[] ip )306
{307
ipFile.Position = offset;308
ipFile.Read( ip,0,ip.Length );309
byte tmp = ip[0];310
ip[0] = ip[3];311
ip[3] = tmp;312
tmp = ip[1];313
ip[1] = ip[2];314
ip[2] = tmp;315
}316

317

318
#region 比较IP地址是否相同319
/// <summary>320
/// 比较IP地址是否相同321
/// </summary>322
/// <param name="ip"></param>323
/// <param name="beginIP"></param>324
/// <returns>0:相等,1:ip大于beginIP,-1:小于</returns>325
#endregion326
private int compareIP( byte[] ip, byte[] beginIP )327
{328
for( int i = 0; i < 4; i++ )329
{330
int r = compareByte( ip[i],beginIP[i] );331
if( r != 0 )332
return r;333
}334
return 0;335
}336

337

338
#region 比较两个字节是否相等339
/// <summary>340
/// 比较两个字节是否相等341
/// </summary>342
/// <param name="bsrc"></param>343
/// <param name="bdst"></param>344
/// <returns></returns>345
#endregion346
private int compareByte( byte bsrc, byte bdst )347
{348
if( ( bsrc&0xFF ) > ( bdst&0xFF ) )349
return 1;350
else if( (bsrc ^ bdst) == 0 )351
return 0;352
else353
return -1;354
}355

356

357
#region 根据当前位置读取4字节358
/// <summary>359
/// 从当前位置读取4字节,转换为长整型360
/// </summary>361
/// <param name="offset"></param>362
/// <returns></returns>363
#endregion364
private long readLong4( long offset )365
{366
long ret = 0;367
ipFile.Position = offset;368
ret |= ( ipFile.ReadByte() & 0xFF );369
ret |= ( ( ipFile.ReadByte() << 8 ) & 0xFF00 );370
ret |= ( ( ipFile.ReadByte() << 16 ) & 0xFF0000 );371
ret |= ( ( ipFile.ReadByte() << 24 ) & 0xFF000000 );372
return ret;373
}374

375

376
#region 根据当前位置,读取3字节377
/// <summary>378
/// 根据当前位置,读取3字节379
/// </summary>380
/// <param name="offset"></param>381
/// <returns></returns>382
#endregion383
private long readLong3( long offset )384
{385
long ret = 0;386
ipFile.Position = offset;387
ret |= ( ipFile.ReadByte() & 0xFF );388
ret |= ( (ipFile.ReadByte() << 8 ) & 0xFF00 );389
ret |= ( (ipFile.ReadByte() << 16 ) & 0xFF0000 );390
return ret;391
}392

393

394
#region 从当前位置读取3字节395
/// <summary>396
/// 从当前位置读取3字节397
/// </summary>398
/// <returns></returns>399
#endregion400
private long readLong3()401
{402
long ret = 0; 403
ret |= ( ipFile.ReadByte() & 0xFF );404
ret |= ( (ipFile.ReadByte() << 8 ) & 0xFF00 );405
ret |= ( (ipFile.ReadByte() << 16 ) & 0xFF0000 );406
return ret;407
}408

409

410
#region 取得begin和end之间的偏移量411
/// <summary>412
/// 取得begin和end中间的偏移413
/// </summary>414
/// <param name="begin"></param>415
/// <param name="end"></param>416
/// <returns></returns>417
#endregion418
private long getMiddleOffset( long begin, long end )419
{420
long records = ( end - begin ) / IP_RECORD_LENGTH;421
records >>= 1;422
if( records == 0 )423
records = 1;424
return begin + records * IP_RECORD_LENGTH;425
}426
} //class QQWry427

428
public class IPLocation 429
{430
public String country;431
public String area;432
433
public IPLocation() 434
{435
country = area = "";436
}437
438
public IPLocation getCopy() 439
{440
IPLocation ret = new IPLocation();441
ret.country = country;442
ret.area = area;443
return ret;444
}445
}446
}447



浙公网安备 33010602011771号