字节序就是多字节数据在计算机中存储或者网络传输过程中地址高低与字节高低顺序关系问题。
大端(big-endian):高地址位存低字节
小端(little-endian):低地址位存低字节
比如:0x0102的存储:
地址递增
大端: 01 02
小端: 02 01
计算机有的是大端有的是小端,但是网络字节序都是大端,所以需要转换。
Linux提供了四个转换函数:
#include <arpa/inet.h> uint32_t htonl(uint32_t hostlong); /*32位主机数据转换为网络字节序的数据*/ uint16_t htons(uint16_t hostshort); /*16位的主机字节序转换为网络字节序*/ uint32_t ntohl(uint32_t netlong); uint16_t ntohs(uint16_t netshort); /*逆函数*/ |
测试网络字节序:
#include
#include
int main(int argc, char **argv)
{
int a = htons(0x0102);
int* p = &a ;
if( *((char*)p) == 0x01 )
printf(" big-endian \n");
if( *((char*)p) == 0x02 )
printf(" little -endian \n");
return 0;
}
测试主机字节序:
#include
#include
int main(int argc, char **argv)
{
int a = 0x0102;
int* p = &a ;
if( *((char*)p) == 0x01 )
printf(" big-endian \n");
else
printf(" little -endian \n");
return 0;
}
#include <netinet/in.h>
struct in_addr
{
in_addr_t s_addr ; /*in_addr_t被定义为无符号整型*/
}
进程使用16位端口号唯一标识。
Linux 地址结构:
#include <netinet/in.h>
/**Linux中网络通信地址结构块/
struct socketaddr_in
{
sa_family_t sin_family; /*16位的地址族*/
in_port_t sin_port; /*16位端口号*/
struct in_adddr sin_addr ; /*32位IP地址*/
unsigned char sin_zero[8]; /* 填充去区,8个字节填“0”*/
}
地址族是根据套接字使用场合不同,会使用不同的地址族,网络通信,使用AF_NET
填充区是为了socketaddr_in和socketaddr结构随意转换
socketaddr结构如下:
#include <netinet/in.h>
struct socketaddr
{
sa_family sa_family;/*16位地址族*/
char sa_data[14];/*14字节填充区*/
}
这两个结构等长,方便强制类型转换
地址形式转换:
二进制转换十进制点分形式
十进制转换二进制
#include <netinet/in.h>
const char * inet_ntop(int domain , const void * restrict addr ,cahr * restrict str , socklen_t size) ;
int inet_pton(int domain , const char * restrict str ,void * restrict addr) ;
domain参数可以是AF_INET或者AF_INET6,地址长度不同;addr表示二进制形式的IP地址;
参数str指向的区域存储IP地址的点分十进制形式的字符串,参数size表示的是该区域的大小,以防止因为地址格式不对导致的越界访问。
因为IP地址字符串形式缓冲区最大为(Iv6地址):3*4+3+1 = 16(字节)
inet_ntop是将二进制转换为十进制
成功返回字符串首地址,地址不对返回0,错误返回-1
inet-pton是上述函数的逆函数
成功返回1
#include
struct hostent * gethostent(void) ;
/*该函数从系统/etc/hosts文件中读取主机相关信息*/
#include
struct hostent
{
char *h_name ;/*正式主机名,只有一个*/
char ** h_aliases;/*主机列表名*/
int h_addrtype;/*IP地址类型可以是v4或者v6*/
int h_length;/*IP地址长度,*/
char ** h_addr_list;/*IP地址列表h_addr_list[0]为主机的IP地址*/
}
#include
#include
#include
#include
#define NET_ADDR 16
int main(int argc, char **argv)
{
struct hostent *host ;
char addr_p[NET_ADDR];
int i ;
if((host = gethostent()) == NULL)
{
printf("error");
exit(1);
}
printf("%s\n",host->h_name) ;
for(i=0; host->h_aliases[i]!=NULL; i++)
{
printf("%s\n",host->h_aliases[i]);
}
if(host->h_addrtype == AF_INET)
printf("AF_INET\n");
else
printf("unix_inet\n");
printf("%d\n", host->h_length) ;
for(i = 0 ;host->h_addr_list[i]!=NULL;i++)
{
printf("%s\n",inet_ntop(host->h_addrtype,host->h_addr_list[i],addr_p,NET_ADDR));
}
return 0;
}