zoukankan      html  css  js  c++  java
  • IP地址与整型数之间的转换

    在Linux中关于IP和无符号整数之间的转换有两个比较好的函数:
    int inet_aton(const char *cp, struct in_addr *inp);
    char *inet_ntoa(struct in_addr in);
    通过函数名就可以知道函数作用了.这里需要注意的是这两个函数操作的结果,或输入的整数都是网络字节序(和大端是一样的),与我们平常的intel机器上的整型数字节序是不一样的.
    不过下面的代码中都没有转化成网络字节序.
    下面的代码是不同的源代码中不同的实现.

    // ip地址结构体  
    struct in_addr  
    {  
        unsigned int s_addr; // network byte order( big-endian)  
    };  
    // inet_aton将 点分十进制串cp 转换为一个网络字节顺序的32位整数 IP地址  
    // 例如将串cp "192.168.33.123 "  
    // 转为 1100 0000   1010 1000    0010 0001     0111 1011   
    // 成功返回1,出错返回0  
    // 转换成功,结果保存在结构体指针ap中  
    int inet_aton(const char *cp, struct in_addr *ap)  
    {  
        int dots = 0;  
        register u_long acc = 0, addr = 0;  
        do {  
                register char cc = *cp;  
                switch (cc)   
                {  
                    case '0':  
                    case '1':  
                    case '2':  
                    case '3':  
                    case '4':  
                    case '5':  
                    case '6':  
                    case '7':  
                    case '8':  
                    case '9':  
                        acc = acc * 10 + (cc - '0');  
                        break;  
                    case '.':  
                        if (++dots > 3)  
                        {  
                            return 0;  
                        }  
                        // Fall through  
                    case '/0':  
                        if (acc > 255)   
                        {  
                            return 0;  
                        }  
                        addr = addr << 8 | acc; // 这句是精华,每次将当前值左移八位加上后面的值  
                        acc = 0;  
                        break;  
                    default:  
                        return 0;  
                }  
        } while (*cp++) ;  
        // Normalize the address   
        if (dots < 3)  
        {  
            addr <<= 8 * (3 - dots) ;  
        }  
        //Store it if requested   
        if (ap)   
        {  
            ap->s_addr = htonl(addr);  
        }  
        return 1;      
    }

    下面是OpenBSD内核中的代码:

    /**
     * Check whether "cp" is a valid ascii representation
     * of an Internet address and convert to a binary address.
     * Returns 1 if the address is valid, 0 if not.
     * This replaces inet_addr, the return value from which
     * cannot distinguish between failure and a local broadcast address.
     */
    int
    inet_aton(const char *cp, struct in_addr *addr)
    {
        register u_int32_t val;
        register int base, n;
        register char c;
        unsigned int parts[4];
        register unsigned int *pp = parts;
        c = *cp;
        for (;;) {
            /**
             * Collect number up to ``.''.
             * Values are specified as for C:
             * 0x=hex, 0=octal, isdigit=decimal.
             */
            if (!isdigit(c))
                return (0);
            val = 0; base = 10;
            if (c == '0') {
                c = *++cp;
                if (c == 'x' || c == 'X')
                    base = 16, c = *++cp;
                else
                    base = 8;
            }
            for (;;) {
                if (isascii(c) && isdigit(c)) {
                    val = (val * base) + (c - '0');
                    c = *++cp;
                } else if (base == 16 && isascii(c) && isxdigit(c)) {
                    val = (val << 4) |
                        (c + 10 - (islower(c) ? 'a' : 'A'));
                    c = *++cp;
                } else
                    break;
            }
            if (c == '.') {
                /**
                 * Internet format:
                 *  a.b.c.d
                 *  a.b.c   (with c treated as 16 bits)
                 *  a.b (with b treated as 24 bits)
                 */
                if (pp >= parts + 3)
                    return (0);
                *pp++ = val;
                c = *++cp;
            } else
                break;
        }
        /**
         * Check for trailing characters.
         */
        if (c != '\0' && (!isascii(c) || !isspace(c)))
            return (0);
        /**
         * Concoct the address according to
         * the number of parts specified.
         */
        n = pp - parts + 1;
        switch (n) {
        case 0:
            return (0);     /** initial nondigit */
        case 1:             /** a -- 32 bits */
            break;
        case 2:             /** a.b -- 8.24 bits */
            if ((val > 0xffffff) || (parts[0] > 0xff))
                return (0);
            val |= parts[0] << 24;
            break;
        case 3:             /** a.b.c -- 8.8.16 bits */
            if ((val > 0xffff) || (parts[0] > 0xff) || (parts[1] > 0xff))
                return (0);
            val |= (parts[0] << 24) | (parts[1] << 16);
            break;
        case 4:             /** a.b.c.d -- 8.8.8.8 bits */
            if ((val > 0xff) || (parts[0] > 0xff) || (parts[1] > 0xff) || (parts[2] > 0xff))
                return (0);
            val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
            break;
        }
        if (addr)
            addr->s_addr = htonl(val);
        return (1);
    }
  • 相关阅读:
    1225. 岛的周长
    238. Product of Array Except Self除自身以外数组的乘积
    RxJava--Buffer,GroupBy 对比
    RxJava--Buffer,GroupBy 对比
    HDU-2182-Frog
    HDU-2182-Frog
    Linux下必知必会文件和目录
    Linux下必知必会文件和目录
    获取一篇新闻的全部信息
    获取一篇新闻的全部信息
  • 原文地址:https://www.cnblogs.com/xkfz007/p/2728715.html
Copyright © 2011-2022 走看看