"The IP address is a 32-bit IP address, which is divided into four segments. Each segment has eight digits, which are expressed in decimal numbers. The value range of each segment is 0 ~ 255. segments and segments are separated by periods ."
As a result, we know that the IP address is actually a 32-bit positive integer. in C #, The uint type can be used, but the SQLServer database does not seem to have a corresponding type; using the int type supported by the database will cause overflow. Therefore, we compromise on using the long (bigint) type.
TIP:
Int value range:-2,147,483,648 to 2,147,483,647
Uint value range: 0 to 4,294,967,295
Long value range:-9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
How can I convert an IP address to an integer? We can see that the IPAddress class has an "[denied]" instance attribute Address, which can indeed return a long value. However, to test this, the obtained data is indeed as follows:
"127.0.0.1"-> 16777343
"127.0.0.2"-> 33554559
It is indeed necessary to make it "reject". Such an integer is meaningless for us. We cannot use this method to compare whether the incoming IP address is between two IP addresses.
If you do this, you can use the GetAddressBytes () instance method of the IPAddress class to obtain the values of the four IP segments and then combine them into an integer, this extension method is provided as follows:
///
/// Convert the IP address to an integer
///
/// Integer
Public static long to an integer (this IPAddress ip)
{
Int x = 3;
Long o = 0;
Foreach (byte f in ip. GetAddressBytes ())
{
O + = (long) f <8 * x --;
}
Return o;
}
You can use this extension method as follows:
IPAddress. Parse ("127.0.0.1"). convert to an integer ()
There is also an extension method for reverse conversion to convert long back to IPAddress:
///
/// Convert the integer into an IP address
///
/// IP address
Public static IPAddress to IP address (this long l)
{
Var B = new byte [4];
For (int I = 0; I <4; I ++)
{
B [3-I] = (byte) (l> 8 * I & 255 );
}
Return new IPAddress (B );
}
In this way, we can obtain correct and meaningful integers through calculation:
"127.0.0.1"-> 2130706433
"127.0.0.2"-> 2130706434
OK. The solution core is established. The SQLServer data table is designed below:
After this design, the starting and ending IP addresses are converted to the long type and saved to the instance, and an expiration time is specified.
During verification, you only need to obtain all unexpired entries and compare whether the Entered IP address is between the starting value and the ending value.
In the previous string storage and verification solutions, either a precise IP address or one or two IP addresses, such as "192. 168. *. * ", it will be very troublesome to block the IP addresses between" 192.168.1.200 "and" 192.168.4.64;
We can easily implement this design: "192.168.1.200" stores "3232235976" in the database, and "192.168.4.64" stores "3232236608" in the database ", even with the naked eye, you can quickly determine whether the incoming addresses are between them, not to mention computer queries.
The EDM model is generated for the data table below:
Code for adding an IP shield record:
///
/// Add a new IP Block
///
///Starting IP address, such as 61.51.200.0
///Terminate an IP address, for example, 61.51.255.255.
///Blocking deadline
/// ID number
Add public static Guid (string IP segment start value, string IP segment end value, DateTime expiration time)
{
Var id = Guid. NewGuid ();
Var sip = IPAddress. Parse (IP segment start value). convert to an integer ();
Var eip = IPAddress. Parse (IP segment termination value). convert to an integer ();
Using (var c = new SiteMainEntities ())
{
// Check whether the same IP address shield record exists
Var a = c. IP address shielding. Where (f => f. Start value of the CIDR Block = sip & f. End value of the CIDR Block = eip );
// If so, update the expiration time.
If (a. Count ()> 0)
{
Var l = a. First ();
If (l. expiration time <expiration time) l. expiration time = expiration time;
}
// If it does not exist, a new shield record is added.
Else c. AddToIP address shielding (new IP address shielding {ID = id, expiration time = expiration time, Region start value = sip, Region end value = eip });
C. SaveChanges ();
}
Return id;
}
Code used to check whether a specified IP address is blocked:
///
/// Check whether the specified IP address is blocked
///
///IP address to be detected
/// Whether the IP address is blocked
Public static bool check whether it is blocked (string IP address)
{
Var ip = IPAddress. Parse (ip address). convert to an integer ();
Using (var c = new SiteMainEntities ())
{
Return c. IP address shielding. count (f => f. expiration time> DateTime. now & ip> = f. start Value & ip <= f. segment termination value)> 0;
}
}
This scheme is much more elegant than the previous string verification scheme and can improve the efficiency of database query. We recommend that you use this scheme in future website development.
Download the PDF version of this article: http://www.box.net/shared/73kuz2bohe
More details