http://roclinux.cn/?p=1160
知識背景:
210.25.132.181屬於IP地址的ASCII表示法,也就是字符串形式。英語叫做IPv4 numbers-and-dots notation。
如果把210.25.132.181轉換為整數形式,是3524887733,這個就是整數形式的IP地址。英語叫做binary data。(其實binary是二進制的意思)
問題所在:
如何在字符串形式的IP和整數形式的IP之間轉換呢?
問題解決思路:
有三個函數可以解決這個問題,當然不止這三個函數,只是這三個函數最常用且最易混淆。
隆重推出他們:inet_network(), inet_addr(), inet_aton()!!
三者定義:
int inet_aton(const char *cp, struct in_addr *inp);
in_addr_t inet_addr(const char *cp);
in_addr_t inet_network(const char *cp);
三者區別:
先說出區別吧,不賣關子。但其實這樣不好,因為我怕你因為知道了結論而不去動手實踐了。(你不會的,是吧? ^_^)
紙上得來終覺淺,絕知此事要躬行。
inet_addr和inet_network函數都是用於將字符串形式轉換為整數形式用的,兩者區別很小,inet_addr返回的整數形式是網絡字節序,而inet_network返回的整數形式是主機字節序。(你一定會納悶,為什么函數叫inet_network,卻返回的是主機字節序,呵呵,就是這么奇怪,你又有什么辦法呢…)其他地方兩者並無二異。他倆都有一個小缺陷,那就是當IP是255.255.255.255時,這兩個“小子”(對這兩個函數的昵稱,請諒解…^_^)會認為這是個無效的IP地址,這是歷史遺留問題,其實在目前大部分的路由器上,這個255.255.255.255的IP都是有效的。
inet_aton函數和上面這倆小子的區別就是在於他認為255.255.255.255是有效的,他不會冤枉這個看似特殊的IP地址。所以我們建議你多多支持這個函數,那兩個小子還是少用為好:)對了,inet_aton函數返回的是網絡字節序的IP地址。
好了,區別就這么簡單,只要你能潛下心來看五分鍾,就OK了。哦,忘了,什么叫網絡字節序,什么叫主機字節序?這兩個概念,如果你不太了解,你最好去找一本socket編程的書籍看一看,我保證沒有5分鍾,你就會了解這兩個概念。
編程舉例:
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<netinet/in.h>
#include<sys/socket.h>
#include<sys/types.h>
int main()
{
char str[]="255.255.255.255";
in_addr_t r1,r2,r3;
struct in_addr inp;
r1=inet_addr(str);
if(r1==-1){
printf("inet_addr return -1 when 255.255.255.255\n");
}else{
printf("inet_addr:ip=%lu\n",ntohl(r1));
}
r2=inet_network(str);
if(r2==-1){
printf("inet_network return -1 when 255.255.255.255\n");
}else{
printf("inet_network:ip=%lu\n",r2);
}
r3=inet_aton(str,&inp);
if(r3==0){
printf("inet_aton return -1 when 255.255.255.255\n");
}else{
printf("inet_aton:ip=%lu\n",ntohl(inp.s_addr));
}
return 0;
} |
你肯定會理解的,只要把str的值稍微修改修改,你就可以得到不同的結果,從而看出其中玄機~~:)
over~
inet_aton,inet_addr和inet_ntoa在點分十進制數串(如,“192.168.1.10")與他的32位網絡字節二進制值之前轉換IPV4地址,有2個比較新的函數inet_pton和inet_ntop,這2個對IPV4和IPV6地址都能處理
#include
#include
#include
int inet_aton(const char *cp, struct in_addr *inp);
in_addr_t inet_addr(const char *cp);
char *inet_ntoa(struct in_addr in);
inet_aton() converts the Internet host address cp from the standard numbers-and-dots notation into binary data and stores it in the structure that inp points to. inet_aton() returns non-zero if the address is valid, zero if not.
inet_aton() 轉換網絡主機地址cp為二進制數值,並存儲在struct in_addr結構中,即第二個參數*inp,函數返回非0表示cp主機有地有效,返回0表示主機地址無效。
The inet_addr() function converts the Internet host address cp from numbers-and-dots notation into binary data in network byte order. If the input is invalid, INADDR_NONE (usually -1) is returned. This is an
obsolete interface to inet_aton(), described immediately above; it is obsolete because -1 is a valid address (255.255.255.255), and inet_aton() provides a cleaner way to indicate error return.
inet_addr函數轉換網絡主機地址(如192.168.1.10)為網絡字節序二進制值,如果參數char *cp無效,函數返回-1(INADDR_NONE),這個函數在處理地址為255.255.255.255時也返回 -1,255.255.255.255是一個有效的地址,不過inet_addr無法處理;
The inet_ntoa() function converts the Internet host address in given in network byte order to a string in standard numbers-and-dots notation. The string is returned in a statically allocated buffer, which subsequent calls will overwrite.
inet_ntoa 函數轉換網絡字節排序的地址為標准的ASCII以點分開的地址,,該函數返回指向點分開的字符串地址的指針,該字符串的空間為靜態分配的,這意味着在第二次調用該函數時,上一次調用將會被重寫(復蓋),所以如果需要保存該串最后復制出來自己管理!
現在一般使用inet_aton和inet_ntoa來處理網絡字節和主機字節之間的轉換;
有兩個更新的函數inet_pton和inet_ntop這2個函數能夠處理ipv4和ipv6,原型如下
#include
#include
#include
int inet_pton(int af, const char *src, void *dst);
這個函數轉換字符串到網絡地址,第一個參數af是地址族,轉換后存在dst中
inet_pton 是inet_addr的擴展,支持的多地址族有下列:
AF_INET
src為指向字符型的地址,即ASCII的地址的首地址(ddd.ddd.ddd.ddd格式的),函數將該地址
轉換為in_addr的結構體,並復制在*dst中
AF_INET6
src為指向IPV6的地址,,函數將該地址
轉換為in6_addr的結構體,並復制在*dst中
如果函數出錯將返回一個負值,並將errno設置為EAFNOSUPPORT,如果參數af指定的地址族和src格式不對,函數將返回0。
函數inet_ntop進行相反的轉換原型如下
#include
#include
#include
const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt);
這個函數轉換網絡二進制結構到ASCII類型的地址,參數的作用和上面相同,只是多了一個參數socklen_t cnt,他是所指向緩存區dst的大小,避免溢出,如果緩存區太小無法存儲地址的值,則返回一個空指針,並將errno置為ENOSPC
例子:
#include
#include
#include
#include
int main(void)
{
char* ip = "192.168.1.87";
struct in_addr inp;
u_int32_t addr = 0x5701a8c0;
inet_aton(ip, &inp);
printf("%x ", inp);
inp.s_addr = addr;
printf("%s \n", inet_ntoa(inp));
return 0;
}
