字节转换函数
本文简单介绍了几个字符排序函数的使用。
大小端字节序
对于一个大于8位的整数,在内存中有两种存储方式:大端字节序及小端字节序;大端字节序是指将二进制数的低字节存放在低地址中;小端字节序则是将低字节放在高地址中。同时,现有的网络协议指定使用大端字节序作为网络传输的字节序,来传送多字节的数据,即网络字节序为大端字节序。
以十进制9999为例,其16位二进制为:0010,0111,0000,1111
。
对于其小端字节序
对于其大端字节序
因此,如果在使用小端字节序的系统中按大端存储十进制9999的话,读出来的结果为0000,1111,0010,0111
,即十进制3879。
字节序转化函数
- uint16_t htons(uint16_t):用于将按本机字节序存储的16位整数转化为网络字节序;
- uint16_t ntohs(uint16_t):用于将按网络字节序存储的16位整数转化为本机字节序;
- uint32_t htonl(uint32_t):用于将按本机字节序存储的32位整数转化为网络字节序;
- uint32_t ntohl(uint32_t):用于将按网络字节序存储的32位整数转化为本机字节序;
以上四个函数名中,h,n,s,l
分别代表主机,网络,短整数,长整数。前两个函数在网络编程中常用于转换端口号,后面个则是用于转换ipv4地址。
- int inet_aton(const char, struct in_addr):用于将ASCII字符串转换为网络字节序,将要转换的字符串的指针传递给第一个参数,第二个参数表示结果要存放的地址。若字符串有效则放回1,无效放回0。
- char *inet_ntoa(struct in_addr*):用于将网络字节序转换为ASCII字符串。
以上两个函数参数中的struct in_addr
是Unix中用来表示网络ipv4地址的结构体。
- int inte_pton(int, const char, void):用于将ASCII字符串转换为网络字节序,第一个参数指明协议族,可以是AF_INET或AF_INET6。将要转换的字符串的指针传递给第二个参数,第三个参数表示结果要存放的地址。若成功则放回1,字符串无效放回0,其他错误返回-1。
- const char inte_ntop(int, const void*, char, size_t):用于将网络字节序转换为ASCII字符串。第三个参数为存储结果的地址,不能为空,调用成功时,这个参数就是该函数的返回值;第四个参数表明空间的大小,ipv4一般为16,ipv6一般为46。
Demo
#include <arpa/inet.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv)
{
printf("This program is used to show the role of several byte order conversion functions\n");
printf("--------------------------------------------------------------------------------\n");
uint16_t host_s;
host_s = atoi(argv[1]);
printf("Function htons and ntohs:\n");
uint16_t network_s = htons(host_s);
printf("\t%hu after fun htons: %hu\n", host_s, network_s);
host_s = ntohs(network_s);
printf("\t%hu after fun ntohs: %hu\n", network_s, host_s);
printf("Function inet_aton and inet_ntoa:\n");
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
char *host_c = argv[2];
if(inet_aton(host_c, &(addr.sin_addr)));
{
printf("\t%s after fun inet_aton: %u\n", host_c, addr.sin_addr.s_addr);
}
printf("\t%u after fun inet_ntoa: %s\n", addr.sin_addr.s_addr,
inet_ntoa(addr.sin_addr));
memset(&addr, 0, sizeof(addr));
printf("Function inet_pton and inet_ntop:\n");
if((inet_pton(AF_INET, host_c, &(addr.sin_addr.s_addr))) == 1)
{
printf("\t%s after fun inet_pton: %u\n", host_c, addr.sin_addr.s_addr);
}
printf("\t%u after fun inet_ntop: %s\n", addr.sin_addr.s_addr,
inet_ntop(AF_INET, &(addr.sin_addr.s_addr), host_c, INET_ADDRSTRLEN));
return 0;
}
结果
This program is used to show the role of several byte order conversion functions
--------------------------------------------------------------------------------
Function htons and ntohs:
9999 after fun htons: 3879
3879 after fun ntohs: 9999
Function inet_aton and inet_ntoa:
127.0.0.1 after fun inet_aton: 16777343
16777343 after fun inet_ntoa: 127.0.0.1
Function inet_pton and inet_ntop:
127.0.0.1 after fun inet_pton: 16777343
16777343 after fun inet_ntop: 127.0.0.1