關於IP地址
IP地址的科普這里就簡單說明一下,更多詳細的知識直接百科吧。
我們知道IPv4地址是由4段0-255的數字組成的,形如:a.b.c.d(0≤a,b,c,d≤255),IPv4也叫32位地址,為什么是32位呢,我們把每一段轉換成二進制之后,它的取值范圍就是00000000-11111111,所以加起來就是32位。
那IP地址的本質是一個32位的二進制數,我們便可以將這個32位的二進制再轉換成十進制,進行比較不就可以了嗎?
IP地址轉十進制
以4.3.2.1為例,對應的十進制是多少呢?
第一步,轉換成二進制,即00000100.00000011.00000010.00000001;
第二步,去掉“.”,得到完整的二進制數:00000100000000110000001000000001;
第三步,再轉回十進制:00000100000000110000001000000001(2)=67305985(10);
所以4.3.2.1對應的十進制數是67305985。
那有沒有什么更快的辦法來計算這個十進制數呢?
肯定是有的,就是移位操作,67305985=4<<24+3<<16+2<<8+1。這樣就實現了IP地址轉十進制數的操作,即使是128位的IPv6,也是如法炮制!
判斷一個IP是否在某個IP段
所以判斷一個是否在某個IP段就直接將要對比的IP地址分別轉換成十進制比大小就好了,也不用擔心什么性能問題,因為移位操作是CPU最擅長做的事情,比起加減乘除還要來得快,因此,我們可以將IP地址轉十進制的操作封裝為一個方法,方便直接調用:
/// <summary> /// IP地址轉換成數字 /// </summary> /// <param name="addr">IP地址</param> /// <returns>數字,輸入無效IP地址返回0</returns> private static uint IPToID(string addr) { if (!IPAddress.TryParse(addr, out var ip)) { return 0; } byte[] bInt = ip.GetAddressBytes(); if (BitConverter.IsLittleEndian) { Array.Reverse(bInt); } return BitConverter.ToUInt32(bInt, 0); }
其中ip.GetAddressBytes()這個操作便是IPAddress自帶的將IP地址按“.”分割后的數組,BitConverter.ToUInt32便是將一組數字進行移位計算得到結果,所以不需要我們再去手動Split和手動移位計算。
基於上面的方法,我們還能進一步封裝一個直接判斷IP地址是否在IP段內的方法:
/// <summary> /// 判斷IP地址在不在某個IP地址段 /// </summary> /// <param name="input">需要判斷的IP地址</param> /// <param name="begin">起始地址</param> /// <param name="ends">結束地址</param> /// <returns></returns> public static bool IpAddressInRange(this string input, string begin, string ends) { uint current = IPToID(input); return current >= IPToID(begin) && current <= IPToID(ends); }
接下來直接測試192.168.2.3是不是在192.168.1.1-192.168.2.255這個網段了,肉眼一看,肯定是在這個地址段內,那看看代碼的執行結果吧。
判斷一個是否在某個IP段其實就這么簡單!
轉載於:https://masuit.com/1802