平時我們使用的IP地址是192.168.1.11這種類型的字符串;而在Linux內核中是用二進制方式表達的IP地址。在程序設計中經常要用到字符串表達方式的IP地址和二進制的IP地址之間的轉換。
面對網絡編程中眾多的地址函數,你hold住了么,tiger哥沒hold住,所以就寫了此篇文章,希望大家能hold住網絡編程。
前言:結構體struct in_addr結構struct in_addr 在文件中定義,結構in_addr 有一個unsigned long int 類型的成員變量s_addr.通常所說的IP地址的二進制形式就保存在成員變量s_addr中。
結構struct in_addr的原型如下:structin_addr{ unsigned long int s_addr;/*IP地址*/ }一。字符串IP地址轉換為二進制形式的IP地址函數1.inet系列函數的原型:#include #include #include int inet_aton(const char *cp,struct in_addr *inp);int addr_t inet_addr(const char *cp);int addr_t inet_network(const char *cp);char * inet_ntoa(struct in_addr in);struct in_addr inet_makeaddr(int net,int host);in_addr_t inet_lnaof(struct in_addr in);in_addr_t inet_netof(struct in_addr in);2.inet_aton()函數int inet_aton(const char*cp,struct in_addr *inp)
1>函數作用:inet_ation()函數將在cp中存儲的點分十進制字符串類型的IP地址,轉換為二進制的IP地址,轉換后的值保存在指針inp指向的結構struct in_addr中。
2>形參? const char *cp:指向字符類型的IP地址。例如“192.168.1.11”? struct in_addr *inp:指向二進制的網絡字節順序的IP地址structin_addr{ unsignedlong s_addr } 3>函數執行成功則返回非0值,參數無效則返回0. 4>實例:#include #include #include
#include #include #include int main()
{ char buffer[32];structin_addr in;in.s_addr =0;/*輸入一個字符串形式的IP地址*/ printf(“pleaseinput the ip addrss\n”);scanf(“%s”,buffer);buffer[31]=‘\0’;printf(“original IP地址:%s\n”,buffer);if( 0 == inet_aton(buffer,&in)){ perror(“inet_aton”);exit(1);} else { printf(“after transfer:0x%0x\n”,in.s_addr);} 5> inet_aton函數最后計算出來的是網絡字節序的二進制IP 3.inet_addr()函數in_addr_t inet_addr(const char *cp)
1>函數作用:它將參數cp所指向的字符串形式的IP地址(“192.168.1.11”)轉換為二進制的網絡字節序的IP地址形式該函數的缺點是:如果IP地址是255.255.255.255.那么調用inet_addr()函數后將返回-1(因為-1的補碼形式是0xFFFFFFFF)。所以不建議使用inet_addr()函數,而是使用inet_aton()函數。
2>函數形參:const char*cp:cp指向字符串形式的IP地址。
3>函數返回值:函數成功后返回二進制的網絡字節序的IP地址(struct in_add),否則返回-1. 4>inet_addr計算出來的是網絡字節序的二進制IP 5>函數實例:#include #include #include
#include #include #include int main()
{ char buffer[32];structin_addr in;in.s_addr =0;/*輸入一個字符串形式的IP地址*/ printf(“pleaseinput the ip addrss\n”);scanf(“%s”,buffer);buffer[31]=‘\0’;printf(“original IPaddress:%s\n”,buffer);if((in.s_addr = inet_addr(buffer))==INADDR_NONE){ perror(“inet_addr”);exit(1);} else { printf(“after transfer:0x%0x\n”,in.s_addr);} 4.inet_network in_addr_t inet_network(constchar *cp)
1>函數作用:將參數cp指向的字符串形式的網絡地址轉換為主機字節順序形式的二進制IP地址。
2>函數形參? const char *cp: cp指向字符串形式的IP地址。
3>函數返回值:執行成功后返回轉換后的結果,參數無效后返回-1. 4>inet_network返回的是主機字節序5>函數實例:#include #include #include
#include #include #include int main()
{ char buffer[32];structin_addr in;in.s_addr =0;/*輸入一個字符串形式的IP地址*/ printf(“pleaseinput the ip addrss\n”);scanf(“%s”,buffer);buffer[31]=‘\0’;printf(“original IPaddress:%s\n”,buffer);if((in.s_addr = inet_addr(buffer))==INADDR_NONE){ perror(“inet_addr”);exit(1);} else { printf(“after transfer:0x%0x\n”,in.s_addr);}總結:1.inet_addr和inet_network函數都是用于將字符串形式轉換為整數形式用的;2.inet_addr返回的整數形式是網絡字節序,而inet_network返回的整數形式是主機字節序。
3.inet_addr 和inet_network有一個小缺陷,那就是當IP是255.255.255.255時,這兩個函數會認為這是個無效的IP地址,這是歷史遺留問題,其實在目前大部分的路由器上,這個 255.255.255.255的IP都是有效的。
4.inet_aton認為255.255.255.255是有效的,所以建議使用inet_aton.并且inet_aton函數返回的是網絡字節序的IP地址。
二。進制IP地址轉換為字符串形式的IP地址1.char * inet_ntoa(struct in_addr in);1>函數作用:將數值為in的網絡字節序形式的二進制IP地址轉換為字符串形式的IP地址。
2>形參:struct in_addr in:指向二進制的IP地址3>函數返回值:執行成功返回結果字符串的指針,參數無效返回NULL. 4>函數實例:#include #include #include
#include #include #include int main()
{ char buffer[32];char *str;structin_addr in;in.s_addr =0;/*輸入一個字符串形式的IP地址*/ printf(“pleaseinput the ip addrss\n”);scanf(“%s”,buffer);buffer[31]=‘\0’;printf(“original IP地址:%s\n”,buffer);if( 0 == inet_aton(buffer,&in)){ perror(“inet_aton”);exit(1);} else { printf(“the first transfer:0x%0x\n”,in.s_addr);} printf(“begin two process:\n”);if( (str =inet_ntoa(in) == NULL ){ printf(“inet_ntoa:argumentinvalid\n”);} else { printf(“thesecond transfer:%s\n”,str);}說明:1.函數inet_ntoa()的返回值為一個指向字符串的指針,該內存函數inet_ntoa()每次調用都會重新覆蓋,因此函數不安全,可能存在某種隱患2.實例:#include #include #include
#include #include #include int main()
{ structin_addr ip1,ip2;char *str1 ;char *str2;ip1.s_addr = 192<<24| 168 <<16 |1 <<8 | 1;ip2.s_addr =255<<24 | 255 <<16 |255<<8|255;str1 = inet_ntoa(ip1);str2 = inet_ntoa(ip2);printf(“ip1:0x%xà%s\n”,ip1.s_addr,str1);printf(“ip2:0x%xà%s\n”,ip2.s_addr,str2);}輸出結果為:ip1: 0xc0a80101à255.255.255.255;ip2:0xffffffffà255.255.255.255;表明函數inet_ntoa在進行二進制IP地址到字符串IP地址的轉換過程中是不可重入的,這個函數轉換兩個不同的IP地址得到了同一個結果。此類函數在調用之后,需要立即將結果取出,沒有取出結果之前不能進行同樣函數的調用。
三。最新的地址轉換函數inet_pton()和inet_ntop()函數inet_pton和inet_ntop這2個函數能夠處理ipv4和ipv6.算是比較新的函數了。inet_pton函數原型如下[將“點分十進制” -> “整數”],并且這兩個函數是一套安全的協議無關的地址轉換函數。所謂安全即這兩個函數是可重入的,并且這些函數支持多種地址類型,包括IPv4和IPv6. 1.inet_pton()函數1>函數功能inet_pton()函數將字符串類型的IP地址轉換為二進制類型。
2>函數原型#include #include #include intinet_pton(int af, const char *src, void *dst);3>函數形參:? int af:af表示網絡類型的協議族,在IPv4下的值為AF_INET;? src:存放需要轉換的字符串? dst :存放轉換后的結果,在IPv4下,dst指向結構struct in_addr的指針。
4>函數返回值當函數inet_pton()的返回值為-1的時候,通常是用于af所指定的協議族不支持造成,此時errno的返回值為EAFNOSUPPORT;當函數的返回值為0時,表示src指向的值不是合法的IP地址;當函數的返回值為正值時,表示轉換成功。
2.inet_ntop()函數1>函數功能inet_pton()函數將二進制的網絡IP地址轉換為字符串。
2>函數原型:#include #include #include intinet_nton(int af, const void *src, char *dst,socklen_t cnt);3>函數形參:? int af:af表示網絡類型的協議族,在IPv4下的值為AF_INET;? src :為需要轉換的二進制IP地址,在IPv4下,src指向一個structin_addr結構類型的指針。? dst指向保存結果緩沖區的指針? cnt的值是dst緩沖區的大小4>函數返回值Inet_ntop()函數返回一個指向dst的指針。當發生錯誤時,返回NULL.當af設定的協議族不支持時,errno設置為EAFNOSUPPORT;當dst緩沖區大小過小的時候errno的值為ENOSPC. 3.函數實例:#include #include #include
#include #include #include int main(int argc,char *argv[])
{ struct in_addr ip;char ipstr[] = “192.168.1.1”;char addr[ADDRLEN];const char * str = NULL;int err = 0;if(err > 0){ printf(“inet_pton:ip %s value is :0x%x\n”,ipstr,ip.s_addr);} //把192.168.12.255轉換為網絡字節序ip.s_addr = htonl(192 << 24 | 168<<16 | 12<<8 | 255);str = (const char *)inet_ntop(AF_INET,(void*)&ip,(char *)&addr[0],ADDRLEN);if(str){ printf(“inet_ntop :ip 0x%x is%s\n”,ip.s_addr,str);}四。inet_makeaddr()函數,inet_lnaof()函數和inet_netof()函數1.struct in_addr inet_makeaddr(int net,int host)
1>函數功能:一個主機的IP地址分為網絡地址和主機地址,inet_makeaddr()函數將主機字節序的網絡地址net和主機地址host合并成一個網絡字節序的IP地址。
2>函數形參:? int net:存放網絡號參數(二進制形式的主機字節序)? int host:存放主機號地址(二進制形式的主機字節序)
3>函數返回值:返回一個網絡字節序的IP地址4>函數實例:unsigned long net,host;net = 0x0000007F;host = 0x00000001;struct in_addr ip = inet_makeaddr(net,hst);2.in_addr_t inet_lnaof(struct in_addr in)