平時(shí)我們使用的IP地址是192.168.1.11這種類型的字符串;而在Linux內(nèi)核中是用二進(jìn)制方式表達(dá)的IP地址。在程序設(shè)計(jì)中經(jīng)常要用到字符串表達(dá)方式的IP地址和二進(jìn)制的IP地址之間的轉(zhuǎn)換。

  面對(duì)網(wǎng)絡(luò)編程中眾多的地址函數(shù),你hold住了么,tiger哥沒(méi)hold住,所以就寫(xiě)了此篇文章,希望大家能hold住網(wǎng)絡(luò)編程。

  前言:結(jié)構(gòu)體struct in_addr結(jié)構(gòu)struct in_addr 在文件中定義,結(jié)構(gòu)in_addr 有一個(gè)unsigned long int 類型的成員變量s_addr.通常所說(shuō)的IP地址的二進(jìn)制形式就保存在成員變量s_addr中。

  結(jié)構(gòu)struct in_addr的原型如下:structin_addr{ unsigned long int s_addr;/*IP地址*/ }一。字符串IP地址轉(zhuǎn)換為二進(jìn)制形式的IP地址函數(shù)1.inet系列函數(shù)的原型:#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()函數(shù)int inet_aton(const char*cp,struct in_addr *inp)

  1>函數(shù)作用:inet_ation()函數(shù)將在cp中存儲(chǔ)的點(diǎn)分十進(jìn)制字符串類型的IP地址,轉(zhuǎn)換為二進(jìn)制的IP地址,轉(zhuǎn)換后的值保存在指針inp指向的結(jié)構(gòu)struct in_addr中。

  2>形參? const char *cp:指向字符類型的IP地址。例如“192.168.1.11”? struct in_addr *inp:指向二進(jìn)制的網(wǎng)絡(luò)字節(jié)順序的IP地址structin_addr{ unsignedlong s_addr } 3>函數(shù)執(zhí)行成功則返回非0值,參數(shù)無(wú)效則返回0. 4>實(shí)例:#include #include #include

  #include #include #include int main()

  { char buffer[32];structin_addr in;in.s_addr =0;/*輸入一個(gè)字符串形式的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函數(shù)最后計(jì)算出來(lái)的是網(wǎng)絡(luò)字節(jié)序的二進(jìn)制IP 3.inet_addr()函數(shù)in_addr_t inet_addr(const char *cp)

  1>函數(shù)作用:它將參數(shù)cp所指向的字符串形式的IP地址(“192.168.1.11”)轉(zhuǎn)換為二進(jìn)制的網(wǎng)絡(luò)字節(jié)序的IP地址形式該函數(shù)的缺點(diǎn)是:如果IP地址是255.255.255.255.那么調(diào)用inet_addr()函數(shù)后將返回-1(因?yàn)?1的補(bǔ)碼形式是0xFFFFFFFF)。所以不建議使用inet_addr()函數(shù),而是使用inet_aton()函數(shù)。

  2>函數(shù)形參:const char*cp:cp指向字符串形式的IP地址。

  3>函數(shù)返回值:函數(shù)成功后返回二進(jìn)制的網(wǎng)絡(luò)字節(jié)序的IP地址(struct in_add),否則返回-1. 4>inet_addr計(jì)算出來(lái)的是網(wǎng)絡(luò)字節(jié)序的二進(jìn)制IP 5>函數(shù)實(shí)例:#include #include #include

  #include #include #include int main()

  { char buffer[32];structin_addr in;in.s_addr =0;/*輸入一個(gè)字符串形式的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>函數(shù)作用:將參數(shù)cp指向的字符串形式的網(wǎng)絡(luò)地址轉(zhuǎn)換為主機(jī)字節(jié)順序形式的二進(jìn)制IP地址。

  2>函數(shù)形參? const char *cp: cp指向字符串形式的IP地址。

  3>函數(shù)返回值:執(zhí)行成功后返回轉(zhuǎn)換后的結(jié)果,參數(shù)無(wú)效后返回-1. 4>inet_network返回的是主機(jī)字節(jié)序5>函數(shù)實(shí)例:#include #include #include

  #include #include #include int main()

  { char buffer[32];structin_addr in;in.s_addr =0;/*輸入一個(gè)字符串形式的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);}總結(jié):1.inet_addr和inet_network函數(shù)都是用于將字符串形式轉(zhuǎn)換為整數(shù)形式用的;2.inet_addr返回的整數(shù)形式是網(wǎng)絡(luò)字節(jié)序,而inet_network返回的整數(shù)形式是主機(jī)字節(jié)序。

  3.inet_addr 和inet_network有一個(gè)小缺陷,那就是當(dāng)IP是255.255.255.255時(shí),這兩個(gè)函數(shù)會(huì)認(rèn)為這是個(gè)無(wú)效的IP地址,這是歷史遺留問(wèn)題,其實(shí)在目前大部分的路由器上,這個(gè) 255.255.255.255的IP都是有效的。

  4.inet_aton認(rèn)為255.255.255.255是有效的,所以建議使用inet_aton.并且inet_aton函數(shù)返回的是網(wǎng)絡(luò)字節(jié)序的IP地址。

  二。進(jìn)制IP地址轉(zhuǎn)換為字符串形式的IP地址1.char * inet_ntoa(struct in_addr in);1>函數(shù)作用:將數(shù)值為in的網(wǎng)絡(luò)字節(jié)序形式的二進(jìn)制IP地址轉(zhuǎn)換為字符串形式的IP地址。

  2>形參:struct in_addr in:指向二進(jìn)制的IP地址3>函數(shù)返回值:執(zhí)行成功返回結(jié)果字符串的指針,參數(shù)無(wú)效返回NULL. 4>函數(shù)實(shí)例:#include #include #include

  #include #include #include int main()

  { char buffer[32];char *str;structin_addr in;in.s_addr =0;/*輸入一個(gè)字符串形式的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);}說(shuō)明:1.函數(shù)inet_ntoa()的返回值為一個(gè)指向字符串的指針,該內(nèi)存函數(shù)inet_ntoa()每次調(diào)用都會(huì)重新覆蓋,因此函數(shù)不安全,可能存在某種隱患2.實(shí)例:#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);}輸出結(jié)果為:ip1: 0xc0a80101à255.255.255.255;ip2:0xffffffffà255.255.255.255;表明函數(shù)inet_ntoa在進(jìn)行二進(jìn)制IP地址到字符串IP地址的轉(zhuǎn)換過(guò)程中是不可重入的,這個(gè)函數(shù)轉(zhuǎn)換兩個(gè)不同的IP地址得到了同一個(gè)結(jié)果。此類函數(shù)在調(diào)用之后,需要立即將結(jié)果取出,沒(méi)有取出結(jié)果之前不能進(jìn)行同樣函數(shù)的調(diào)用。

  三。最新的地址轉(zhuǎn)換函數(shù)inet_pton()和inet_ntop()函數(shù)inet_pton和inet_ntop這2個(gè)函數(shù)能夠處理ipv4和ipv6.算是比較新的函數(shù)了。inet_pton函數(shù)原型如下[將“點(diǎn)分十進(jìn)制” -> “整數(shù)”],并且這兩個(gè)函數(shù)是一套安全的協(xié)議無(wú)關(guān)的地址轉(zhuǎn)換函數(shù)。所謂安全即這兩個(gè)函數(shù)是可重入的,并且這些函數(shù)支持多種地址類型,包括IPv4和IPv6. 1.inet_pton()函數(shù)1>函數(shù)功能inet_pton()函數(shù)將字符串類型的IP地址轉(zhuǎn)換為二進(jìn)制類型。

  2>函數(shù)原型#include #include #include intinet_pton(int af, const char *src, void *dst);3>函數(shù)形參:? int af:af表示網(wǎng)絡(luò)類型的協(xié)議族,在IPv4下的值為AF_INET;? src:存放需要轉(zhuǎn)換的字符串? dst :存放轉(zhuǎn)換后的結(jié)果,在IPv4下,dst指向結(jié)構(gòu)struct in_addr的指針。

  4>函數(shù)返回值當(dāng)函數(shù)inet_pton()的返回值為-1的時(shí)候,通常是用于af所指定的協(xié)議族不支持造成,此時(shí)errno的返回值為EAFNOSUPPORT;當(dāng)函數(shù)的返回值為0時(shí),表示src指向的值不是合法的IP地址;當(dāng)函數(shù)的返回值為正值時(shí),表示轉(zhuǎn)換成功。

  2.inet_ntop()函數(shù)1>函數(shù)功能inet_pton()函數(shù)將二進(jìn)制的網(wǎng)絡(luò)IP地址轉(zhuǎn)換為字符串。

  2>函數(shù)原型:#include #include #include intinet_nton(int af, const void *src, char *dst,socklen_t cnt);3>函數(shù)形參:? int af:af表示網(wǎng)絡(luò)類型的協(xié)議族,在IPv4下的值為AF_INET;? src :為需要轉(zhuǎn)換的二進(jìn)制IP地址,在IPv4下,src指向一個(gè)structin_addr結(jié)構(gòu)類型的指針。? dst指向保存結(jié)果緩沖區(qū)的指針? cnt的值是dst緩沖區(qū)的大小4>函數(shù)返回值Inet_ntop()函數(shù)返回一個(gè)指向dst的指針。當(dāng)發(fā)生錯(cuò)誤時(shí),返回NULL.當(dāng)af設(shè)定的協(xié)議族不支持時(shí),errno設(shè)置為EAFNOSUPPORT;當(dāng)dst緩沖區(qū)大小過(guò)小的時(shí)候errno的值為ENOSPC. 3.函數(shù)實(shí)例:#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轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)序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()函數(shù),inet_lnaof()函數(shù)和inet_netof()函數(shù)1.struct in_addr inet_makeaddr(int net,int host)

  1>函數(shù)功能:一個(gè)主機(jī)的IP地址分為網(wǎng)絡(luò)地址和主機(jī)地址,inet_makeaddr()函數(shù)將主機(jī)字節(jié)序的網(wǎng)絡(luò)地址net和主機(jī)地址host合并成一個(gè)網(wǎng)絡(luò)字節(jié)序的IP地址。

  2>函數(shù)形參:? int net:存放網(wǎng)絡(luò)號(hào)參數(shù)(二進(jìn)制形式的主機(jī)字節(jié)序)? int host:存放主機(jī)號(hào)地址(二進(jìn)制形式的主機(jī)字節(jié)序)

  3>函數(shù)返回值:返回一個(gè)網(wǎng)絡(luò)字節(jié)序的IP地址4>函數(shù)實(shí)例: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)