3.7.3 网络地址的数据结构和操作函数

3.7.3 网络地址的数据结构和操作函数

使用套接字进行网络编程,离不开一个重要的因素——网络地址,在套接字中网络地址有其特定的数据结构和表示方式,以下对网络地址的数据结构和相关操作进行介绍。

1.地址相关数据结构

在Internet通信域中标识一个网络应用进程需要3个要素:IP地址、端口和协议类型。因此,在套接字中需要有相关的数据结构来表达这几个要素,在套接字编程接口的函数中要用到它们。

(1)通用地址结构

这类地址结构可以描述多种网络协议,并不仅仅限于TCP/IP协议族。

·sa_family:描述使用的是哪类协议族,如果是使用TCP/IP协议族,则该值为AF_INET。

·sa_data:以上述参数指定的协议族描述的网络地址,如果是使用TCP/IP协议族,则见后续描述。

(2)INET协议族网络地址结构

地址结构名sockaddr_in中的最后两个字母“in”是Internet的简写,说明该结构适用于采用TCP/IP协议的网络。

·sin_family:地址族,一般填为AF_INET。

·sin_port:16位的IP端口,必须注意字节序问题。

·sin_addr:32位的IPv4地址

·sin_zero:8个字节的0值填充。

(3)IPv4地址结构

该结构提供了3种赋值的接口S_un_b和S_un_w、S_addr,最常见的是S_addr、S_un_b这两种,以下介绍这两种方法。

·使用S_addr接口赋值

S_addr:32位的无符号整数,对应32位IPv4地址。要将地址202.112.107.165赋值给in_addr结构,可以使用如下代码:

其中inet_addr是一个常用的地址转换函数,用于将点分十进制字符串格式的IP地址转换成u_long格式的IP地址。

由于有定义

故也可以将上面的代码简写为

·使用S_un_b接口赋值

S_un_b:包含4个8位无符号整数,组合起来标识IPv4地址:s_b1.s_b2.s_b3.s_b4。以下例子将IPv4地址202.112.107.165赋值给addr。

2.地址转换函数

在表示IP地址时,直观的表示常采用点分十进制,如202.112.107.165,但在套接字API中,IP地址是用无符号长整型数来表示的,也称为网络字节序的IP地址。为此套接字编程接口设置了两个函数,专门用于两种形式的IP地址转换。

(1)inet_addr函数

函数作用:将点分十进制形式的网络地址转换为无符号长整型数形式。

函数定义:unsigned long inet_addr(const char*cp)。

入口参数cp:点分十进制形式的IP地址,如“202.112.107.165”。

返回值:网络字节序的IP地址,是无符号的长整数。

(2)inet_ntoa函数

函数作用:将in_addr结构表示的网络地址转为点分十进制形式。

函数定义:char*inet_ntoa(struct in_addr in)。

入口参数in:包含长整型IP地址的in_addr结构变量。

返回值:指向点分十进制IP地址的字符串的指针。

3.域名服务函数

通常情况下书写一个网址时都使用域名来标识站点,但是在程序中需要使用IP地址,使用域名服务函数可以将文字型的主机域名直接转换成IP地址。

gethostbyname函数

函数定义:struct hostent*gethostbyname(const char*name)。

入口参数:站点的主机域名字符串。

返回值:指向hostent结构的指针。

hostent结构包含主机名、主机别名数组、返回地址的类型(一般为AF_INET)、地址长度的字节数和已符合网络字节顺序的主机网络地址等。

4.本机字节序和网络字节序

不同的计算机系统采用不同的字节序存储数据。例如,在Intel体系结构中,多字节存储采取“低位在前,高位在后”的方式,一个两字节的数据0x0102,字节0x01存储在低位,字节0x02存储在高位;而在Macintosh等体系结构中,多字节存储采用“高位在前,低位在后”的方式,同样的两字节数据0x0102,字节0x01存储在高位,字节0x02存储在低位。一个给定的计算机系统的多字节存储顺序,称为本机字节序。

在网络协议中,多字节数据的存储采用的是“高位在前,低位在后”的字节存储顺序,在网络协议中的多字节存储顺序称为网络字节序。由于主机字节序有两种,并且这两种主机字节序都被广泛使用,这就给不同类别主机间的网络数据交互设计带来了一定的麻烦,为了解决这个问题,在套接字API中提供了一组字节序处理函数进行本机字节序和网络字节序之间的转换。作为程序开发者,只需要简单调用以下函数,不用考虑本机字节序与网络字节序是否有差别。

·htons():短整数本机字节序转换为网络字节序,用于端口号。

·htonl():长整数本机字节序转换为网络字节序,用于IP地址。

·ntohs():短整数网络字节序转换为主机字节序,用于端口号。

·ntohl():长整数网络字节序转换为本机字节序,用于IP地址。

函数名称中的n代表网络(network),h代表主机(host),l代表无符号长整型(long),s代表无符号短整型(short)。

下例的代码片段说明了如何构造一个完整的地址数据结构。