目录
一、Linux下IP地址的表示方式
1.1、通用套接字的地址类型定义如下:
1.2、以太网中的地址类型表示
1.3、结构sockaddr和结构sockaddr_in的关系
1.4、本地socket中使用的地址类型
二、IP地址的转换
? 2.1 字符串IP与二进制IP地址的转换
2.2 IP转换函数之通用的版本
在socket编程中,地址结构通常都是以sockaddr_开头的,不同的协议族有不同的地址后缀定义方式
上述结构中,定义在头文件<ifaddrs.h>中,sa_family_t实际上是 unsigned short int类型,故该结构的共占用16个字节。
从上面可以看出,在以太网编程中,使用struct sockaddr结构并不是很方便,没法直观的标示IP地址和端口等相关的信息,为此在以太网编程中,使用struct sockaddr_in来描述网络地址信息,其结构如下:
上述结构中,struct in_addr是使用一个uint32_t 网络字节序描述的IP地址信息,我们在转换成点分式的IP信息时,就是使用的该结构体中in_addr_t进行转换的。
上面两节描述了通用的socket地址和以太网中使用的地址,那么,这两种结构有啥关系呢,其实,通过上面的结构体介绍,已经可以看到一个大概,sockaddr和sockaddr_in是一个同样大小的结构,其对应关系如下图:
在sockaddr_in中,只使用了前面的8个字节,为了和sockaddr中保持结构大小一直,其后面的8个字节填充保留。
在使用bind等相关函数时,通常都是使用的地址sockaddr,这样,我们在实际以太网编程使用的过程中,都是利用结构sockaddr_in进行地址信息的设置,然后使用强转为sockaddr类型
在进程间通信中,也可以使用socket进行通信,与网络编程类似,其也有一个地址描述信息结构体,其结构体说明如下:
其中,sun_family的取值一般使用AF_UNIX或者AF_LOCAL,sun_path是一个路径名。
上一章中,介绍了在网络编程中常用的几个与ip地址相关的数据结构,看完上面的一章,我们可能有这样的疑问,上面提到的IP地址都是用一个uint32_t 表示的,但是我们在实际中,见到的一般都是192.168.1.xx这种点分式的表示方法,那么,这两者之间如何转换?linux提供了一系列的函数,来完成这个工作。
Linux系统中提供了一组函数用于网络地址的字符串形式和二进制形式之间的转换,其形式为inet_xxx(),函数具体如下:
inet_aton()函数
该函数将cp中的十进制字符串类型的IP地址,转换为二进制的IP地址,转换成功后的值,保存在指向结构体 struct in_addr 中,由上一章可以知道,该结构中为 struct sockaddr_in中的一个变量。当转换成功时,返回一个非0值,当转换失败或者传入的一个非法地址时,返回值为0。
inet_addr()函数
该函数与inet_aton()函数类似,也是将字符串形式的字符串转换为二进制的IP地址,转换成功返回IP地址,这个IP地址时网络字节序的表达,如果转换失败或者参数非法,返回-1,因为-1的存储形式为(111111111111111),而IP地址255.255.255.255也是这个值,故不能使用这个函数对这个地址进行转换。
inet_ntoa()函数
该函数是将一个struct in_addr表示的一个IP地址转换为点分十进制的字符串IP地址,返回值是转换后的字符串指针,这个指针是该函数返回的,该函数会用一个静态区域保存该返回结果,有可能结果会被其他线程调用覆盖这个结果,故该函数并不是线程安全的,使用时需要注意。
在2.1节中,描述了常用的几个IP地址各种形式之间的转换函数,通过描述,可以知道,这几个函数或多或少存在缺陷,如只支持IPV4,或者不是线程安全的。下面介绍一对安全的与协议无关的地址转换函数,这两个函数都是可以重入支持多线程的,且这些函数支持IPv4和IPv6。
inet_pton()函数
该函数是将字符串类型的IP地址转换为二进制类型,第一个参数af表示网络类型的协议族,在IPv4下的值为AF_INET,第二个参数src表示需要转换的字符串,第三个参数表示转换后的结构,在IPv4中,dst指向的是一个struct in_addr的结构体指针。该函数的返回值为-1的时候,通常是第一个参数af指定的协议族不支持造成的。当函数的返回值为0时,表示src指向的值不是合法的IP地址,当返回值为正值时,表示转换成功。
inet_ntop()函数