Linux网络编程IP地址的字符串与网络字节序转换
向sockaddr_in注入地址时,需要将ip地址的字符串形式转化为网络字节序的形式;而相反地,网络字节序也能转化回字符串形式。用到的函数分别inet_addr()、inet_aton()、inet_ntoa()、inet_pton()、inet_ntop(),转化的方向如下图。
1 inet_addr()
#include <arpa/inet.h>
in_addr_t inet_addr(const char *ip);
- 功能:是将一个点分十进制ipv4的IP地址转换32位大端网络字节序整数
- 参数:点分十进制的ip地址字符串ip
- 返回值:成功时返回32位大端整数,失败返回INADDR_NONE
2 inet_aton()和inet_ntoa()
inet_addr()
直接返回结果,而inet_aton()
将转换结果直接写入传入的参数中,方便向sockaddr_in注入IP地址。
记法:ASCII to network / network to ASCII
inet_aton()
#include <arpa/inet.h>
int inet_aton(const char *ip, struct in_addr *addr);
- 功能:是将一个点分十进制的ipv4的IP地址转换32位大端网络字节序整数,结果直接填入in_addr中,使用频率比
inet_addr()
多。 - 参数:
- string: 点分十进制的ip地址字符串ip
- addr: 属于sockaddr_in结构体的结构体in_addr地址
- 返回值:成功时返回1,失败返回0
inet_ntoa()
#include <arpa/inet.h>
char *inet_ntoa(struct in_addr *addr );
- 功能:是将一个32位大端网络字节序整数转换为点分十进制的ipv4的IP地址。
- 参数:
- addr: 属于sockaddr_in结构体的结构体in_addr地址
- 返回值:存放转化结果的首地址,char*指针,要提前分配空间。失败时返回-1。
3 inet_pton()inet_ntop()
前面的只适用于ipv4地址,这两个适用于ipv4和ipv6,因此使用时要指定地址族
记法:presentation to numeric / numeric to presentation
inet_pton()
#include <arpa/inet.h>
int inet_pton(int af, const char *ip, void *dst);
- 功能:将ipv4或者ipv6的字符串ip地址转换为大端网络字节序整数
- 参数:
- af: 地址族,取值为AF_INET和AF_INET6,分别ipv4和ipv6
- ip:要转化的ip字符串首地址
- dst:接收转化后大端网络字节序整数结果的地址,ipv4可以用sin_addr
- 返回值:如果函数出错将返回一个负值,并将errno设置为EAFNOSUPPORT,如果参数af指定的地址族和ip格式不对,函数将返回0。
inet_ntop()
#include <arpa/inet.h>
const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt);
- 功能:将为大端网络字节序整数转换为ipv4或者ipv6的字符串ip地址
- 参数:
- af: 地址族,取值为AF_INET和AF_INET6,分别ipv4和ipv6
- src:大端网络字节序整数首地址地址,ipv4可以用sin_addr
- dst:接收转化后的ip地址字符串首地址(缓冲区)
- cnt:dst缓冲区大小
- 返回值:
如果缓存区太小无法存储地址的值,则返回一个空指针,并将errno置为ENOSPC。若无错误发生,Inet_ntop()函数返回一个指向缓冲区的指针。
例程
代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
int main()
{
char ip1[] = "192.168.0.74";
char fakeip[] = "192.256.0.74";
struct sockaddr_in addr_inet;
/*
inet_addr()
*/
printf("ip %s converting\n",ip1);
unsigned long net_ordered_addr = inet_addr(ip1);
if(net_ordered_addr == INADDR_NONE)
{
printf("inet_addr() error\n\n");
}else{
printf("inet_addr() success: network ordered integer addr: %#x \n\n",
net_ordered_addr);
}
// fake ip
printf("fake ip %s converting\n", fakeip);
net_ordered_addr = inet_addr(fakeip);
if(inet_aton(fakeip,&addr_inet.sin_addr)==0)
{
printf("inet_addr() error\n\n");
}else{
printf("inet_addr() success: network ordered integer addr: %#x \n\n",
net_ordered_addr);
}
/*
inet_aton() and inet_ntoa()
*/
printf("ip %s converting\n",ip1);
if(inet_aton(ip1,&addr_inet.sin_addr)==0)
{
printf("inet_aton() error\n\n");
}else{
printf("inet_aton() success: network ordered integer addr: %#x \n\n",
addr_inet.sin_addr.s_addr);
}
printf("network odered addr %#x converting\n",addr_inet.sin_addr.s_addr);
char *ip_new;
ip_new = inet_ntoa(addr_inet.sin_addr);
if(ip_new[0]== -1){
printf("inet_ntoa() error\n\n");
}else{
printf("inet_ntoa() success: ip: %s \n\n", ip_new);
}
/*
inet_pton() and inet_ntop()
*/
char ip2[] = "255.255.255.255";
printf("ip %s converting\n", ip2);
if(!inet_pton(AF_INET, ip2, (void *) &addr_inet.sin_addr))
{
printf("inet_pton() error\n\n");
}else{
printf("inet_pton() success: network ordered integer addr: %#x \n\n",
addr_inet.sin_addr);
}
char ip2_new[16]; //ipv4的字符串长度为16字节
printf("network odered addr %#x converting\n", addr_inet.sin_addr.s_addr);
if(!inet_ntop(AF_INET, (void *) &addr_inet.sin_addr, ip2_new, sizeof(ip2_new)))
{
printf("inet_pton() error\n\n");
}else{
printf("inet_pton() success: ip: %s \n\n", ip2_new);
}
return 0;
}