自己实现inet_aton和inet_ntoa函数功能

之前遇到过要自己实现 inet_atoninet_ntoa 函数的问题,这里总结一下。

1 基本知识

网络字节序是大端模式,那么内存中的低地址存放的是数据的高位,内存中的高地址存放的是数据的低位。 inet_aton 是将IPv4地址(点分法)转换成对应的十进制整数;而 inet_ntoa 是将十进制整数转换成对应的IPv4地址(点分法)

2 完整代码

/**
 * @FileName    network_selfdefine.c
 * @Describe    A simple example for using sigprocmask and sigsuspend functions in linux.
 * @Author      vfhky 2016-04-08 13:11 https://typecodes.com/cseries/networkselfdefineconv.html
 * @Compile     gcc network_selfdefine.c -o network_selfdefine
 */
#include 
#include 
#include "print.h"
#define IP_ADRESS "192.168.1.177"

/*
 * 将IPv4地址(点分法)转换成对应的十进制整数
 * 原函数声明:
 * int inet_aton(const char *cp, struct in_addr *inp);
 */
unsigned int __inet_aton( const char *c_ipaddr )
{
    unsigned int u_ipaddr = 0;
    unsigned int u_tmp = 0;
    char c;
    int i_base = 10;
    int i_shift = 0;
    int i_recycle = 0;

    c = *c_ipaddr;
    while( 1 )
    {
        u_tmp = 0;
        while( 1 )
        {
            //如果是数字
            if( isdigit(c) )
            {
                u_tmp = (u_tmp * i_base) + (c - 0x30);
                c = *++c_ipaddr;
            }
            else
            {
                //如果不是数字而是.符号,说明.符号前面的数据已经处理完毕
                break;
            }
        }

        //字节移位,注意网络字节序是大端模式
        i_shift = 8*i_recycle++;
        u_tmp <<= i_shift;
        u_ipaddr += u_tmp;

        //对点(.)符号的处理
        if( c == '.' )
        {
            c = *++c_ipaddr;
        }
        else
        {
            //如果是其它符号(例如结束符等)则跳出整个循环
            break;
        }
    }

    //检查是否包含非结束符、空格等符号,是则返回0
    if( c != '' && ( !isspace(c) ) )
        goto ret_0;

    return u_ipaddr;
ret_0:
    return (0);
}

/**
 * 将十进制整数转换成对应的IPv4地址(点分法),其中由于网络字节序是大端表示,所以第一个字节对应的是整数的低位byte[0]
 * 原函数声明:
 * int inet_aton(const char *cp, struct in_addr *inp);
 */
static char buffer[16];
char *  __inet_ntoa( unsigned int in )
{
    unsigned char *bytes = (unsigned char *) &in;
    snprintf( buffer, sizeof (buffer), "%d.%d.%d.%d", bytes[0], bytes[1], bytes[2], bytes[3] );
    return buffer;
}

int main( int argc, char **argv )
{
    PRINT( "IP_ADRESS[%s] ==> [%lu].", IP_ADRESS, __inet_aton( IP_ADRESS ) );
    PRINT( "[%lu]=[0x%x].", __inet_aton( IP_ADRESS ), __inet_aton( IP_ADRESS ) );
    PRINT( "Network orders[%lu] ==> [%s].", __inet_aton( IP_ADRESS ), __inet_ntoa(__inet_aton( IP_ADRESS )) );
    return 0;
}</=

3 编译执行

使用 《Linux C/C++工程中可生成ELF、动/静态库文件的通用Makefile》 一文中的Makefile文件进行程序编译(当然也可以使用命令进行编译 gcc network_selfdefine.c -o network_selfdefine ),接着执行该程序,得到如下图所示的结果:

需要说明的是从第结果中的 [2969675968]=[0xb101a8c0]. 可以看出,低字节的0xC0(即192)由于大端模式存放在内存中的高位,高字节的0xB1(即177)存放在内存中的低位。

4 附录

关于 inet_aton 的man说明:

[vfhky@typecodes xlei]$ man inet_aton
INET(3)                         Linux Programmer's Manual                        INET(3)

NAME
       inet_aton,   inet_addr,   inet_network,   inet_ntoa,  inet_makeaddr,  inet_lnaof,
       inet_netof - Internet address manipulation routines

SYNOPSIS
       #include 
       #include 
       #include 

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

   Feature Test Macro Requirements for glibc (see feature_test_macros(7)):

       inet_aton(), inet_ntoa(): _BSD_SOURCE || _SVID_SOURCE

DESCRIPTION
       inet_aton() converts the Internet host address cp from the IPv4  numbers-and-dots
       notation  into binary form (in network byte order) and stores it in the structure
       that inp points to.  inet_aton() returns nonzero if the address is valid, zero if
       not.

关于 inet_aton 的man说明:

[vfhky@typecodes ~]$ man inet_ntoa
INET(3)                         Linux Programmer's Manual                        INET(3)

NAME
       inet_aton,   inet_addr,   inet_network,   inet_ntoa,  inet_makeaddr,  inet_lnaof,
       inet_netof - Internet address manipulation routines

SYNOPSIS
       #include 
       #include 
       #include 

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

   Feature Test Macro Requirements for glibc (see feature_test_macros(7)):

       inet_aton(), inet_ntoa(): _BSD_SOURCE || _SVID_SOURCE

DESCRIPTION
       inet_aton() converts the Internet host address cp from the IPv4  numbers-and-dots
       notation  into binary form (in network byte order) and stores it in the structure
       that inp points to.  inet_aton() returns nonzero if the address is valid, zero if
       not.
TypeCodes稿源:TypeCodes (源链) | 关于 | 阅读提示

本站遵循[CC BY-NC-SA 4.0]。如您有版权、意见投诉等问题,请通过eMail联系我们处理。
酷辣虫 » 后端存储 » 自己实现inet_aton和inet_ntoa函数功能

喜欢 (0)or分享给?

专业 x 专注 x 聚合 x 分享 CC BY-NC-SA 4.0

使用声明 | 英豪名录