一,字节序
大端(存储)模式:是指数据的低位字节内容保存在内存的高地址处,而数据的高位字节内容保存在内存的低地址处。
小端(存储)模式:是指数据的低位字节内容保存在内存的低地址处,而数据的高位字节内容,保存在内存的高地址处。
在ubuntn下查看大小端模式
readelf -a 可执行文件
代码判断当前机器的字节序
#include <stdio.h>
//方法1
int check_sys()
{
int i=1;
return (*(char*)&i);
}
//方法2
int check_sys()
{
union
{
int i;
char c;
}un;
un.i=1;
return un.c;
}
int main()
{
int ret=check_sys();
if(ret==1)
{
printf("小端\n");
}
else
{
printf("大端\n");
}
return 0;
}
注意:
- 网络协议指定了通讯字节序为大端
- 只有在多字节数据(>=2)和非0处理时才需要考虑字节序
- 运行在同一台计算机上的进程相互通信时,一般不用考虑字节序
- 不同计算机之间通讯,需要转换自己的字节序为网络字节序
在需要字节序转换的时候一般调用特定字节序转换函数
主机字节序和网络字节序转换API
htonl(发送方调用)
#include <arpa/inet.h>
uint32_t htonl(uint32_t hostint32);
功能 | 将32位主机字节序转换成网络字节序数据(IP地址) |
参数 | uint32_t:unsigned int hostint32:待转换的32位主机字节序数据 |
返回值 | 成功:返回网络字节序的值 |
htons(发送方调用)
#include <arpa/inet.h>
uint16_t htons(uint16_t hostint16);
功能 | 将16位主机字节序转换成网络字节序数据(端口号) |
参数 | uint16_t:unsigned short int hostint16:待转换的16位主机字节序数据 |
返回值 | 成功:返回网络字节序的值 |
ntohl(接收方调用)
#include <arpa/inet.h>
uint32_t ntohl(uint32_t hostint32);
功能 | 将32位网络字节序数据转换成主机字节序数据(IP地址) |
参数 | hostint32:待转换的32位网络字节序数据 |
返回值 | 成功:返回主机字节序的值 |
ntohs(接收方调用)
#include <arpa/inet.h>
uint16_t ntohs(uint16_t hostint16);
功能 | 将16位网络字节序数据转换成主机字节序数据(端口号) |
参数 | hostint32:待转换的16位网络字节序数据 |
返回值 | 成功:返回主机字节序的值 |
案例
#include <stdio.h>
#include <arpa/inet.h>
int main()
{
unsigned int a=0x12345678;
uint32_t b=htonl(a);
printf("网络字节序:%#x\n",b);
uint32_t c=ntohl(b);
printf("主机字节序:%#x\n",c);
uint32_t n_port=htons(8000);
printf("n_port:%u\n",n_port);
printf("n_port:%u\n",ntohs(n_port));
return 0;
}
地址转换函数
inet_pton (发送方,转换完成之后就是大端)
#include <arpa/inet.h>
int inet_pton(int family,const char* strptr,void* addrptr);
功能:将点分十进制数串转换成32位无符号整数
参数: family:协议族 AF_INET(IPV4) ,AF_INET6(IPV6)
strptr:点分十进制数串 (例如:192.168.2.20)
addrptr:32位无符号整数的地址
返回值:成功返回1,失败返回其他
inet_ntop(接收方)
#include <arpa/inet.h>
int inet_ntop(int family,const char* addrptr,char* strptr,size_t len);
功能:将32位无符号整数转换成点分十进制数串
参数:family:协议族 AF_INET(IPV4) ,AF_INET6(IPV6)
addrptr:32位无符号整数
strptr:点分十进制数串
len:strptr缓存区长度
返回值:
成功:则返回字符串的首地址
失败:返回NULL
案例
#include <stdio.h>
#include <arpa/inet.h>
int main()
{
//将点分十进制IP地址转成32为无符号32网络字节序
unsigned int ip;
inet_pton(AF_INET,"10.7.121.127",&ip);
printf("ip=%u\n",ip);
//将无符号32网络字节序转成点分十进制IP地址字符串
unsigned char ip_buf[16]="";
inet_ntop(AF_INET,&ip,ip_buf,16);
printf("ip_buf=%s\n",ip_buf);
printf("-------------------\n");
//ip地址存放分析
unsigned char* p=(unsigned char*)&ip;
printf("自己实现:%u.%u.%u.%u\n",p[0],p[1],p[2],p[3]);
return 0;
}