Unix网络编程(二):字节排序与地址转换函数

1.简介

在进行unix网络编程时,总是分不清什么时候需要用到字节操作函数,并且在遇到这些函数时十分陌生。于是,便有了这篇文章

2.why

内存中存储数据有两种方式:大端与小端。假设起始存放地址为1000
1. 小端:低权重字节在低地址处。例如 0x1122, 0x11<<8 是高权重字节,所以其在高地址1001处;0x22是低权重字节,所以在1000处。小端也是符合我们平常思维方式的储存方法。
2. 大端:高权重字节在低地址处。例如 0x5566, 0x55<<8 是高权重字节,所以在低地址1000处。0x66(低权重)在高地址1001处。

不同的体系架构的计算机,内存储存方式就不统一,所以在网络通信时需要一个统一的字节顺序,网际通信协议使用大端字节,这个就是网络字节序

3.when

那么在什么时候需要使用网络字节序呢?在查阅了一些资料后,发现端口号和ip地址必须转换成网络字节序。在传输数据时,short和long型数据最好转换,而字符串发送和接受却不需要转换。这里希望明白的朋友交流一下,为什么字符串发送不需要转换,是因为ASCII的关系吗?

参考: 网络传输数据要不要转换大小端字节序的问题

4.How

那么怎么将数据转换成网络字节序呢?这里可以分成两种,第一种对于整型变量的转换,第二种是对于IP地址的转换。

  • 对于整型(short/int/long)变量来说,
//123(主机序) ---> 123(网络字节序)
//用于发送时
uint16_t htons(uint16_t host16bitvalue);
uint32_t htonl(uint32_t host32bitvalue);

以上的两个函数是将主机字节序”host”转换成网络字节序”net”。”s”代表short,转换的是16-bit的整型;”l”代表long,转换的是32-bit的整型。

与之相对的,是网络字节序转换成主机字节序。

//456(网络序) ---> 456(主机序)
//用于接收时
uint16_t ntohs(uint16_t net16bitvalue);
uint32_t ntohl(uint32_t net32bitvalue);
  • 对于ip地址而言

    ip地址的形式,我们最常用的是“点分式”的字符串ip地址,即使是域名地址,最后也需要转换分点分式的ip格式再进行连接。所以,对于ip地址,将其转化成网络字节序,就是将其(点分式的)字符串转换成网络字节序

#include <arpa/inet.h>
//以下仅适用与IPv4

//"address" to net,即ip地址 ---> 网络字节序
//例如 "192.168.1.106" --> struct in_addr
//若strptr(address字符串)有效,则返回1。否则返回0
int inet_aton(const char *strptr, struct in_addr *addrptr);

//net to "address"
//返回值是点分式的字符串ip地址
char *inet_ntoa(struct in_addr inaddr);

//address to net 的另一种形式
//通过返回值而不是指针返回ip地址的网络字节序
in_addr_t inet_addr(const char *strptr);

注意,上面的三个函数仅适用于IPv4的地址

下面,将介绍IPv4/v6通用的转换函数:

//IPv4/v6通用转换函数

/** * @brief inet_pton "presentation" to net * * @param strptr -- const char *, presentation, 例如 "192.168.1.100" * @param addrptr -- void *, 通过指针返回in_addr或in6_ddr结构体 * * @returns 成功返回1,否则返回0 */
int inet_pton(int family, const char *strptr, void *addrptr);

/** * @brief inet_ntop * * @param family 协议族,AF_INET或AF_INET6 * @param addrptr -- const void *, 要转换的in_addr或in6_addr * @param strptr -- char *,存放转换的结果 * @param len -- size_t,目标储存单元(strptr)的大小 * 通常为 INET_ADDRSTRLEN(16) 或 INET6_ADDRSTRLEN(46) * @returns 转换结果的指针,即 strptr */
const char* inet_ntop(int family, const void *addrptr, char *strptr, size_t len);

你可能感兴趣的:(unix,网络编程)