Pure qq ip database
Copy codeThe Code is as follows: using System;
Using System. Collections. Generic;
Using System. Text;
Using System. IO;
Using System. Web;
Using System. Configuration;
Namespace BLL
{
Public class IPLocationSearch
{
Private static readonly QQWry qq = new QQWry (ConfigurationManager. etettings ["ip"] + "qqwry. dat ");
Public static IPLocation GetIPLocation (string ip)
{
Return qq. SearchIPLocation (ip );
}
}
/*
Usage:
Example:
BDQQ. Data. QQWry qq = new BDQQ. Data. QQWry ("d: \ QQWry. Dat ");
BDQQ. Data. IPLocation ip = qq. SearchIPLocation ("127.0.0.1"); // Add an ip address here
Console. WriteLine (ip. country); // country
Console. WriteLine (ip. area); // Region
*/
// The following is a class file
// Rewrite it based on LumaQQ.
/**/
/// <Summary>
/// Summary of QQWry.
/// </Summary>
Public class QQWry
{
// The first Mode
# Region first Mode
/**/
/// <Summary>
/// The first Mode
/// </Summary>
# Endregion
Private const byte REDIRECT_MODE_1 = 0x01;
// Second mode
# Region second mode
/**/
/// <Summary>
/// Second mode
/// </Summary>
# Endregion
Private const byte REDIRECT_MODE_2 = 0x02;
// The length of each record
# Region length of each record
/**/
/// <Summary>
/// The length of each record
/// </Summary>
# Endregion
Private const int IP_RECORD_LENGTH = 7;
// Database file
# Region database file
/**/
/// <Summary>
/// File object
/// </Summary>
# Endregion
Private FileStream ipFile;
Private const string unCountry = "unknown country ";
Private const string unArea = "Unknown Region ";
// Start position of the Index
# Region index start position
/**/
/// <Summary>
/// Start position of the Index
/// </Summary>
# Endregion
Private long ipBegin;
// Index end position
# Region index end position
/**/
/// <Summary>
/// Index end position
/// </Summary>
# Endregion
Private long ipEnd;
// Ip address object
# Region IP address object
/**/
/// <Summary>
/// IP object
/// </Summary>
# Endregion
Private IPLocation loc;
// Store text content
# Region stores text content
/**/
/// <Summary>
/// Store text content
/// </Summary>
# Endregion
Private byte [] buf;
// Store 3 bytes
# Region stores 3 bytes
/**/
/// <Summary>
/// Store 3 bytes
/// </Summary>
# Endregion
Private byte [] b3;
// Store 4 bytes
# Region stores 4 bytes
/**/
/// <Summary>
/// Store 4-byte IP addresses
/// </Summary>
# Endregion
Private byte [] b4;
// Constructor
# Region Constructor
/**/
/// <Summary>
/// Constructor
/// </Summary>
/// <Param name = "ipfile"> absolute path of the IP database file </param>
# Endregion
Public QQWry (string ipfile)
{
Buf = new byte [100];
B3 = new byte [3];
B4 = new byte [4];
Try
{
IpFile = new FileStream (ipfile, FileMode. Open );
}
Catch (Exception ex)
{
Throw new Exception (ex. Message );
}
IpBegin = readLong4 (0 );
IpEnd = readLong4 (4 );
Loc = new IPLocation ();
}
// Search by IP Address
# Region search by IP Address
/**/
/// <Summary>
/// Search for IP addresses
/// </Summary>
/// <Param name = "ip"> </param>
/// <Returns> </returns>
# Endregion
Public IPLocation SearchIPLocation (string ip)
{
// Convert the character IP address to byte
String [] ipSp = ip. Split ('.');
If (ipSp. Length! = 4)
{
Throw new ArgumentOutOfRangeException ("it is not a legal IP address! ");
}
Byte [] IP = new byte [4];
For (int I = 0; I <IP. Length; I ++)
{
IP [I] = (byte) (Int32.Parse (ipSp [I]) & 0xFF );
}
IPLocation local = null;
Long offset = locateIP (IP );
If (offset! =-1)
{
Local = getIPLocation (offset );
}
If (local = null)
{
Local = new IPLocation ();
Local. area = unArea;
Local. country = unCountry;
}
Return local;
}
// Obtain specific information
# Region
/**/
/// <Summary>
/// Obtain specific information
/// </Summary>
/// <Param name = "offset"> </param>
/// <Returns> </returns>
# Endregion
Private IPLocation getIPLocation (long offset)
{
IpFile. Position = offset + 4;
// Read the first byte to determine whether it is a flag byte
Byte one = (byte) ipFile. ReadByte ();
If (one = REDIRECT_MODE_1)
{
// The first Mode
// Read the country offset
Long countryOffset = readLong3 ();
// Go to the offset
IpFile. Position = countryOffset;
// Check the flag byte again
Byte B = (byte) ipFile. ReadByte ();
If (B = REDIRECT_MODE_2)
{
Loc. country = readString (readLong3 ());
IpFile. Position = countryOffset + 4;
}
Else
Loc. country = readString (countryOffset );
// Read the region flag
Loc. area = readArea (ipFile. Position );
}
Else if (one = REDIRECT_MODE_2)
{
// Second mode
Loc. country = readString (readLong3 ());
Loc. area = readArea (offset + 8 );
}
Else
{
// Normal Mode
Loc. country = readString (-- ipFile. Position );
Loc. area = readString (ipFile. Position );
}
Return loc;
}
// Obtain region information
# Region obtain region information
/**/
/// <Summary>
/// Read the region name
/// </Summary>
/// <Param name = "offset"> </param>
/// <Returns> </returns>
# Endregion
Private string readArea (long offset)
{
IpFile. Position = offset;
Byte one = (byte) ipFile. ReadByte ();
If (one = REDIRECT_MODE_1 | one = REDIRECT_MODE_2)
{
Long areaOffset = readLong3 (offset + 1 );
If (areaOffset = 0)
Return unArea;
Else
{
Return readString (areaOffset );
}
}
Else
{
Return readString (offset );
}
}
// Read the string
# Region read string
/**/
/// <Summary>
/// Read the string
/// </Summary>
/// <Param name = "offset"> </param>
/// <Returns> </returns>
# Endregion
Private string readString (long offset)
{
IpFile. Position = offset;
Int I = 0;
For (I = 0, buf [I] = (byte) ipFile. ReadByte (); buf [I]! = (Byte) (0); buf [++ I] = (byte) ipFile. ReadByte ());
If (I> 0)
Return Encoding. Default. GetString (buf, 0, I );
Else
Return "";
}
// Find the absolute offset of the IP address
# Region: Find the absolute offset of the IP address
/**/
/// <Summary>
/// Find the absolute offset of the IP address
/// </Summary>
/// <Param name = "ip"> </param>
/// <Returns> </returns>
# Endregion
Private long locateIP (byte [] ip)
{
Long m = 0;
Int r;
// Compare the first IP Address
ReadIP (ipBegin, b4 );
R = compareIP (ip, b4 );
If (r = 0)
Return ipBegin;
Else if (r <0)
Return-1;
// Start Binary Search
For (long I = ipBegin, j = ipEnd; I <j ;)
{
M = this. getMiddleOffset (I, j );
ReadIP (m, b4 );
R = compareIP (ip, b4 );
If (r> 0)
I = m;
Else if (r <0)
{
If (m = j)
{
J-= IP_RECORD_LENGTH;
M = j;
}
Else
{
J = m;
}
}
Else
Return readLong3 (m + 4 );
}
M = readLong3 (m + 4 );
ReadIP (m, b4 );
R = compareIP (ip, b4 );
If (r <= 0)
Return m;
Else
Return-1;
}
// Read the 4-byte IP Address
# Region read 4-byte IP Address
/**/
/// <Summary>
/// Read four bytes from the current location. These four bytes are IP addresses.
/// </Summary>
/// <Param name = "offset"> </param>
/// <Param name = "ip"> </param>
# Endregion
Private void readIP (long offset, byte [] ip)
{
IpFile. Position = offset;
IpFile. Read (ip, 0, ip. Length );
Byte tmp = ip [0];
Ip [0] = ip [3];
Ip [3] = tmp;
Tmp = ip [1];
Ip [1] = ip [2];
Ip [2] = tmp;
}
// Compare whether the IP address is the same
# Check whether the IP address of region is the same
/**/
/// <Summary>
/// Compare whether the IP address is the same
/// </Summary>
/// <Param name = "ip"> </param>
/// <Param name = "beginIP"> </param>
/// <Returns> 0: equal, 1: ip address greater than beginIP,-1: less than </returns>
# Endregion
Private int compareIP (byte [] ip, byte [] beginIP)
{
For (int I = 0; I <4; I ++)
{
Int r = compareByte (ip [I], beginIP [I]);
If (r! = 0)
Return r;
}
Return 0;
}
// Compare whether two bytes are equal
# Region compares two bytes for Equality
/**/
/// <Summary>
/// Compare whether two bytes are equal
/// </Summary>
/// <Param name = "bsrc"> </param>
/// <Param name = "bdst"> </param>
/// <Returns> </returns>
# Endregion
Private int compareByte (byte bsrc, byte bdst)
{
If (bsrc & 0xFF)> (bdst & 0xFF ))
Return 1;
Else if (bsrc ^ bdst) = 0)
Return 0;
Else
Return-1;
}
// Read 4 bytes according to the current position
# Region reads 4 bytes from the current location
/**/
/// <Summary>
/// Read 4 bytes from the current position and convert it to a long integer
/// </Summary>
/// <Param name = "offset"> </param>
/// <Returns> </returns>
# Endregion
Private long readLong4 (long offset)
{
Long ret = 0;
IpFile. Position = offset;
Ret | = (ipFile. ReadByte () & 0xFF );
Ret | = (ipFile. ReadByte () <8) & 0xFF00 );
Ret | = (ipFile. ReadByte () <16) & 0xFF0000 );
Ret | = (ipFile. ReadByte () <24) & 0xFF000000 );
Return ret;
}
// Read 3 bytes based on the current location
# Region reads 3 bytes based on the current location
/**/
/// <Summary>
/// Read 3 bytes based on the current location
/// </Summary>
/// <Param name = "offset"> </param>
/// <Returns> </returns>
# Endregion
Private long readLong3 (long offset)
{
Long ret = 0;
IpFile. Position = offset;
Ret | = (ipFile. ReadByte () & 0xFF );
Ret | = (ipFile. ReadByte () <8) & 0xFF00 );
Ret | = (ipFile. ReadByte () <16) & 0xFF0000 );
Return ret;
}
// Read 3 bytes from the current location
# Region reads 3 bytes from the current location
/**/
/// <Summary>
/// Read 3 bytes from the current location
/// </Summary>
/// <Returns> </returns>
# Endregion
Private long readLong3 ()
{
Long ret = 0;
Ret | = (ipFile. ReadByte () & 0xFF );
Ret | = (ipFile. ReadByte () <8) & 0xFF00 );
Ret | = (ipFile. ReadByte () <16) & 0xFF0000 );
Return ret;
}
// Get the offset between begin and end
# Region obtains the offset between begin and end.
/**/
/// <Summary>
/// Get the offset between begin and end
/// </Summary>
/// <Param name = "begin"> </param>
/// <Param name = "end"> </param>
/// <Returns> </returns>
# Endregion
Private long getMiddleOffset (long begin, long end)
{
Long records = (end-begin)/IP_RECORD_LENGTH;
Records> = 1;
If (records = 0)
Records = 1;
Return begin + records * IP_RECORD_LENGTH;
}
} // Class QQWry
Public class IPLocation
{
Public String country;
Public String area;
Public IPLocation ()
{
Country = area = "";
}
Public IPLocation getCopy ()
{
IPLocation ret = new IPLocation ();
Ret. country = country;
Ret. area = area;
Return ret;
}
}
}