下面我们来看一篇关于C语言中实现inet_aton和inet_ntoa函数功能的例子,希望这篇文章能够对各位带来帮助,具体的如下所示。
之前遇到过要自己实现inet_aton和inet_ntoa函数功能的问题,这里总结一下。
1 基本知识
网络字节序是大端模式,那么内存中的低地址存放的是数据的高位,内存中的高地址存放的是数据的低位。 inet_aton是将IPv4地址(点分法)转换成对应的十进制整数;而inet_ntoa是将十进制整数转换成对应的IPv4地址(点分法)。
2 完整代码
#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
{
//如果是其它符号(例如结束符\0等)则跳出整个循环
break;
}
}
//检查是否包含非结束符、空格等符号,是则返回0
if( c != '\0' && ( !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 *) ∈
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),接着执行该程序,得到如下图所示的结果:
自己实现inet_aton和inet_ntoa函数功能
需要说明的是从第87行输出的[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.