inet_addr和inet_aton

inet_addr的功能是将一个ip地址字符串转换成一个整数值。一般的IP地址串格式为:'a.b.c.d'分成四段。
但是也会有分为1、2或3段的格式。下面我们来看看WIN2K下inet_addr函数的源码:

[cpp]  view plain copy
  1. unsigned long PASCAL  
  2. inet_addr(  
  3.     IN const char *cp  
  4.     )  
  5. {  
  6.         register unsigned long val, base, n;  
  7.         register char c;  
  8.         unsigned long parts[4], *pp = parts;  
  9.   
  10.         WS_ENTER( "inet_addr", (PVOID)cp, NULL, NULL, NULL );  
  11. again:  
  12.         /* 
  13.          * Collect number up to ``.''. 
  14.          * Values are specified as for C: 
  15.          * 0x=hex, 0=octal, other=decimal. 
  16.          */  
  17.         val = 0; base = 10;  //每段中根据中根据前缀知道其使用的进制。  
  18.         if (*cp == '0') {    //0X前缀为十六进制;0前缀为八进制;缺省为十进制  
  19.                 base = 8, cp++;  
  20.                 if (*cp == 'x' || *cp == 'X')  
  21.                         base = 16, cp++;  
  22.     }  
  23.       
  24.         //下面这段代码是用来取得IP地址的一段将其转换值整数  
  25.         while (c = *cp) {  
  26.                 if (isdigit(c)) {                         //若为数字,则将其转换至数字进行计算  
  27.                         val = (val * base) + (c - '0');   //注意,在W2K下这儿有一个BUG,因为当为8进制时没有  
  28.                         cp++;                             //检查是否为8、9数字;这个问题在XP下修正了。  
  29.                         continue;  
  30.                 }  
  31.                 if (base == 16 && isxdigit(c)) {  //当为16进制时,检查是否为‘a’~ 'f'字母  
  32.                         val = (val << 4) + (c + 10 - (islower(c) ? 'a' : 'A'));  
  33.                         cp++;  
  34.                         continue;  
  35.                 }  
  36.                 break;  
  37.         }  
  38.        //当为‘.’时,此时表示地址段结束了。  
  39.         if (*cp == '.') {  
  40.                 /* 
  41.                  * Internet format: 
  42.                  *      a.b.c.d 
  43.                  *      a.b.c   (with c treated as 16-bits) 
  44.                  *      a.b     (with b treated as 24 bits) 
  45.                  */  
  46.                 /* GSS - next line was corrected on 8/5/89, was 'parts + 4' */  
  47.                 if (pp >= parts + 3) {                   //若为‘.’间隔,检查是否已经超过3个了。  
  48.                         WS_EXIT( "inet_addr", -1, TRUE );//因为最多为3个‘.’  
  49.                         return ((unsigned long) -1);     //在W2K下可以看出允许直接以‘.’开头的IP地址      
  50.                 }                                        //而在XP下是不允许的。  
  51.                 *pp++ = val, cp++;  
  52.                 goto again;  
  53.         }  
  54.   
  55.         /* 
  56.          * Check for trailing characters.//到此处时,要么结束,要么为出错字符 
  57.          */                              //只有为0或者空格是结束,否则出错。         
  58.         if (*cp && !isspace(*cp)) {  
  59.                 WS_EXIT( "inet_addr", -1, TRUE );  
  60.                 return (INADDR_NONE);  
  61.         }  
  62.         *pp++ = val;  
  63.         /* 
  64.          * Concoct the address according to 
  65.          * the number of parts specified. 
  66.          */  
  67.         n = (unsigned long)(pp - parts);  
  68.         switch ((int) n) {  
  69.   
  70.         case 1:                         /* a -- 32 bits */  //当为一个段a时,直接就是这个值。  
  71.                 val = parts[0];  
  72.                 break;  
  73.   
  74.         case 2:                         /* a.b -- 8.24 bits */    //当为两个段a.b时,整数值构成XX  XX XX XX  
  75.                 if ((parts[0] > 0xff) || (parts[1] > 0xffffff)) { //                           --  --------  
  76.                     WS_EXIT( "inet_addr", -1, TRUE );             //                           a       b     
  77.                     return(INADDR_NONE);  
  78.                 }  
  79.                 val = (parts[0] << 24) | (parts[1] & 0xffffff);  
  80.                 break;  
  81.   
  82.         case 3:                         /* a.b.c -- 8.8.16 bits *///当为3个段a.b.c时,整数值构成XX  XX   XX XX  
  83.                 if ((parts[0] > 0xff) || (parts[1] > 0xff) ||     //                            --  --   -----  
  84.                     (parts[2] > 0xffff)) {                        //                            a    b     c  
  85.                     WS_EXIT( "inet_addr", -1, TRUE );  
  86.                     return(INADDR_NONE);  
  87.                 }  
  88.                 val = (parts[0] << 24) | ((parts[1] & 0xff) << 16) |  
  89.                         (parts[2] & 0xffff);  
  90.                 break;  
  91.   
  92.         case 4:          /* a.b.c.d -- 8.8.8.8 bits *///当为4个段a.b.c.d时,整数值构成XX  XX   XX   XX  
  93.                 if ((parts[0] > 0xff) || (parts[1] > 0xff) ||        //               --  --   --   --  
  94.                     (parts[2] > 0xff) || (parts[3] > 0xff)) {        //               a    b    c    d  
  95.                     WS_EXIT( "inet_addr", -1, TRUE );  
  96.                     return(INADDR_NONE);  
  97.                 }  
  98.                 val = (parts[0] << 24) | ((parts[1] & 0xff) << 16) |  
  99.                       ((parts[2] & 0xff) << 8) | (parts[3] & 0xff);  
  100.                 break;  
  101.   
  102.         default:  
  103.                 WS_EXIT( "inet_addr", -1, TRUE );  
  104.                 return (INADDR_NONE);  
  105.         }  
  106.         val = htonl(val);  
  107.         WS_EXIT( "inet_addr", val, FALSE );  
  108.         return (val);  
  109. }  
原文地址: http://blog.csdn.net/misterliwei/article/details/2318725


inet_addr 将"数字+句点"的格式的IP地址转换到unsigned long中,返回值已经是按照网络字节顺序的
相反inet_ntoa把类型为struct in_addr的数据转化为"数字+句点"的形式的字符串
typedef u_int32_t in_addr_t;
struct in_addr
{
       in_addr_t s_addr;
};

本机字节顺序与网络字节顺序的转换
#include <arpa/inet.h>
htons  ------"host to network short"
htonl   -------"host to network long"
ntohs  -------"network to host short"
ntohl   -------"network to host long"
*注意:在你的数据放到网络上的时候,确信它是网络字节顺序
网络字节顺序(大端字节)和x86机器字节顺序(小端字节)
eg:0X3132  在x86上显示21  在网络传输中为12

inet_addr返回的整数形式是网络字节序,而inet_network返回的整数形式是主机字节序。他俩都有一个小缺陷,
那就是当IP是255.255.255.255时,这两个函数会认为这是个无效的IP地址,这是历史遗留问题,其实在目前大部
分的路由器上,这个255.255.255.255的IP都是有效的。
inet_aton函数和上面这俩个函数的区别就是在于他认为255.255.255.255是有效的,他不会冤枉这个看似特殊的IP地址。对了,inet_aton函数返回的是网络字节序的IP地址。

综上所述,应该使用inet_aton和inet_ntoa这一对函数。


资料:

#include <sys/socket.h>
#include <netinet/ in.h>
#include <arpa/inet.h>

typedef uint32_t in_addr_t;

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);
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);


 

//  Internet address.
struct in_addr {
        union {
                 struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b;
                 struct { u_short s_w1,s_w2; } S_un_w;
                u_long S_addr;  /*  port in network byte order  */
        } S_un;
#define s_addr  S_un.S_addr
};
//  Socket address, internet style.
struct sockaddr_in {         //  struct sockaddr的一种特殊形式
         short            sin_family;     /*  address family: AF_INET  */
        u_short        sin_port;         /*  port in network byte order  */
         struct in_addr sin_addr;         /*  port in network byte order  */
         char            sin_zero[8];     /*  8 byte pad  */
};
//  Structure used by kernel to store most addresses.
struct sockaddr {
        u_short sa_family;  /*  address family  */
         char    sa_data[14];  /*  up to 14 bytes of direct address  */
};

struct in_addr {
    unsigned  long  int s_addr;
}


原文地址: http://www.cppblog.com/toMyself/archive/2010/08/13/123353.aspx




你可能感兴趣的:(inet_addr和inet_aton)