一、socket 地址API
在介绍地址API前先弄清什么是大端字节序、小端字节序,主机字节序、网络字节序。
大端字节序:指一个整数的高位字节存储在内存的低地址处,低位字节存储在内存的高地址处。
小端字节序:指整数的高位字节存储在内存的高地址处,而低位字节存储在内存的低地址处。
主机字节序:以大端字节序或小端字节来作为机器字序。现代PC大多采用小端字节序,因此小端字节序被称为主机字节序。而网络字节序则采用大端字节序。
当两台使用不同字节序的主机进行数据传输时,发送端总是把要发送的数据转换成大端字节序(网络字节序)数据后再发送,而接收端则可以根据自身采用的字节序决定是否对接收到的数据进行转换。
在linux下提供以下4个函数完成主机字节序和网络字节序之间的转换:
可编写代码来测试自己主机是采用哪种字节序,代码如下:#include <netinet/in.h> uint32_t htonl(uint32_t hostlong); uint16_t htons(uint16_t hostshort); uint32_t ntohl(uint32_t netlong); uint16_t ntohs(uint16_t netshort);
void byteorder() { union { short s; char c[sizeof(short)]; }un; un.s = 0x0102; if (un.c[0] == 1 && un.c[1] == 2) { printf("big-endian\n"); } else if (un.c[0] == 2 && un.c[1] == 1) { printf("little-endian\n"); } else { printf("unknown\n"); } }
通用sockaddr地址:
在socket网络编程接口中表示socket地址的具体结构是sockaddr:
注:成员sa_data根据不同的地址族具有不同的值:struct sockaddr { sa_faimly_t sa_family; /* 地址族类型,如AF_INET,AF_INET6,AF_UNIX */ char sa_data[14]; /* sockfet地址值 */ };
AF_UNIX sa_data是文件的路径名,长度可达到108字节。
AF_INET sa_data的值是16位端口号和32位IPV4地址。
AF_INET6 sa_data的值是16位端口号、32位流标识、128位IPV6地址和32位范围ID。14字节的sa_data成员根据无法完全容纳多协议族的地址值,因些linux又提供了一个新的通用sockaddr地址:
struct sockaddr_storage { sa_family_t sa_family; unsigned long int __ss_align; //此成员用于内存对齐 char __ss_padding[128-sizeof(__ss_align)]; }