#include#include #ifdef WIN32 #include #else #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef WIN32 #pragma comment(lib,"wsock32.lib") #endif /*參數UINT32都為網絡字節順序。*/ /*IP地址是否合法, 合法返回TURE,失敗返回FALSE*/ int netIpIsValid(_UINT32 IP) { int i; struct in_addr addr; addr.s_addr = IP; i = inet_addr(inet_ntoa(addr)); if((i == 0)||(i == 0xffffffff)) return FALSE; else return TRUE; } /*MASK子網掩碼是否合法, 合法返回TURE,失敗返回FALSE*/ int netMaskIsValid(_UINT32 mask) { int i; unsigned long ii; i = netIpIsValid(mask); if(i==TRUE) { ii = ntohl(mask); if((ii|ii-1)==0xffffffff) { return TRUE; } } return FALSE; } /*MASK子網掩碼是否合法, 合法返回TURE,失敗返回FALSE*/ int netMaskAndIpIsValid(_UINT32 IP, _UINT32 mask) { int i; int a, b=0, c; i = netIpIsValid(IP); if(i!=TRUE) return FALSE; i = netMaskIsValid(mask); if(i!=TRUE) return FALSE; a = IP&0x000000ff; b = ntohl(mask); /*首先與默認子網掩碼比較*/ if(a>0&&a<127) { if(mask<0x000000ff) return FALSE; if(mask>0x000000ff) b-=0xff000000; } if(a>=128&&a<=191) { if(mask<0x0000ffff) return FALSE; if(mask>0x0000ffff) b-=0xffff0000; } if(a>=192&&a<=223) { if(mask<0x00ffffff) return FALSE; if(mask>0x00ffffff) b-=0xffffff00; } /*每個子網段的第一個是網絡地址,用來標志這個網絡,最後一個是廣播地址,用來代表這個網絡上的所有主機.這兩個IP地址被TCP/IP保留,不可分配給主機使用.*/ c = ~ntohl(mask)&ntohl(IP); if(c==0||c==~ntohl(mask)) return FALSE; /*RFC 1009中規定劃分子網時,子網號不能全為0或1,會導致IP地址的二義性*/ if(b>0) { c = b&(ntohl(IP)); if(c==0||c==b) return FALSE; } return TRUE; } /*測試主網和子網是否匹配,也可測試兩個主機IP是否在同一網段內*/ int netIPAndSubnetValid(_UINT32 IP, _UINT32 subIP, _UINT32 mask) { int i; int addr1, addr2; i = netMaskAndIpIsValid(IP, mask); if(i!=TRUE) return FALSE; i = netMaskAndIpIsValid(subIP, mask); if(i!=TRUE) return FALSE; addr1 = IP&mask; addr2 = subIP&mask; if(addr1!=addr2) return FALSE; return TRUE; }
技術實現及功能:
1. 用C語言實現
2. 判斷IP地址是否合法
3. 判斷MASK是否合法
4. 判斷MASK和IP地址組合是否合法
測試:
測試環境:win7 VC++;
測試結果:
1、測試IP是否合法:
輸入IP為0xFFFFFFFF即255.255.255.255,結果為不合法;
輸入IP為0x00000000即0.0.0.0,結果為不合法;
輸入IP為0x00000000--0xFFFFFFFF即在0.0.0.0--255.255.255.255之間(全0和全1除外),結果為合法。
2、測試子網掩碼是否合法:
輸入0x00C0FFFF(1111 1111.1111 1111.1100 0000),結果合法;
輸入一個無符號int型數,二進制形式為 左邊為全1右邊為全0,結果合法,其余形式不合法。
3、測試子網掩碼和IP是否匹配:
輸入IP為0x410AA8C0即192.168.10.65(C類IP),輸入子網掩碼為0xC0FFFFFF,結果匹配,輸入小於0x00FFFFFF的子網掩碼時不匹配;
輸入IP為0x0141A885即133.168.65.1(B類IP),輸入子網掩碼為0x00C0FFFF,結果匹配,輸入小於0x0000FFFF的子網掩碼時不匹配;
輸入IP為0x0100413F即63.65.0.1(A類IP),輸入子網掩碼為0x0000C0FF,結果匹配,輸入小於0x000000FF的子網掩碼時不匹配。
子網段內第一個和最後一個IP不可分配;子網號全0或全1的子網不可用,此時的結果都為不匹配。
4、測試兩個IP是否在同一子網段:
輸入兩個IP為0x0C81C480 0x118FC480,輸入子網掩碼為0x00C0FFFF,結果為兩個IP在同一網段;
輸入兩個IP為0x0C81C480 0x117FC480,輸入子網掩碼為0x00C0FFFF,結果兩個IP不在同一網段。
備注:測試數據為無符號int型,網絡字節順序。
補充知識:
一般的,32位的IP地址分為兩部分,即網絡號和主機號,我們分別把他們叫做IP地址的“網間網部分”和“本地部分”。子網編址技術將本地部分進一步劃分為“物理網絡”部分和“主機”部分,其中“物理網絡”用於標識同一IP網絡地址下的不同物理網絡,即是“子網”。
A類IP段 0.0.0.0 到127.255.255.255
B類IP段 128.0.0.0 到191.255.255.255
C類IP段 192.0.0.0 到223.255.255.255
XP默認分配的子網掩碼每段只有255或0
A類的默認子網掩碼 255.0.0.0 一個子網最多可以容納1677萬多台電腦
B類的默認子網掩碼 255.255.0.0 一個子網最多可以容納6萬台電腦
C類的默認子網掩碼 255.255.255.0 一個子網最多可以容納254台電腦
以C類地址為例。IP地址中的前3個字節表示網絡號,後一個字節既表明子網號,又說明主機號,還說明兩個IP地址是否屬於一個網段。如果屬於同一網絡區間,這兩個地址間的信息交換就不通過路由器。如果不屬同一網絡區間,也就是子網號不同,兩個地址的信息交換就要通過路由器進行。
看一個例子:
A的IP地址:11000000,10101000,00000000,00000101
子網掩碼:11111111,11111111,11111111,00000000
B的IP地址:11000000,10101000,00000000,00010110
看上邊的內容,子網掩碼在左邊一共有24位為1,那這樣的意思就是如果兩個IP地址的前24位都相同的話,那這兩個IP地址就是在同一個網段內,看到我紅色標記的A和B的地址都相同,那這就說明A和B在同一個網段內。
再看一個例子,如果還是A地址的數據發到C地址,C的IP地址為192.168.56.21
A的IP地址:11000000,10101000,00000000,00000101
子網掩碼:11111111,11111111,11111111,00000000
C的IP地址:11000000,10101000,00111000,00010101
看上邊的A和C,按照子網掩碼的要求,如果C的前24位和A的前24位都相同的話,那麼A和C才是同一網段的,看上邊C的地址,我用藍色來標注不同的位數,這樣A 和C就不在同一個網段內,路由器就不能直接把A要發給C的數據直接經過一個路由器給發送過去,這樣路由器就要先將A的數據轉發到另外一個路由器(一個不行就繼續往下發),然後再發到C上。
● 字節序轉換函數
htons 把 unsigned short 類型從主機序轉換到網絡序
htonl 把 unsigned long 類型從主機序轉換到網絡序
ntohs 把 unsigned short 類型從網絡序轉換到主機序
ntohl 把 unsigned long 類型從網絡序轉換到主機序
這幾個函數很好記,比如htons中hton代表host to network, s代表unsigned short
char FAR * inet_ntoa( struct in_addr in);
將一個IP轉換成一個互聯網標准點分格式的字符串。
in_addr_t inet_addr(const char *cp);
將一個點分十進制的IP轉換成一個長整數型數(u_long類型)。返回值已是網絡字節順序,可以直接作為internet 地址
一個函數返回值為TRUE或FALSE 只有這兩種返回值時 在判斷返回值時不用 if(i==TRUE)或if(i==FALSE),而用if(i) if(!i) 編程規范。
inet_ntoa()返回的字符串是臨時裝在一個靜態分配的緩沖區裡面,下一次調用此函數的時候緩沖區會被重寫