一、Linux下的地址结构
typedef uint32_t in_addr_t;
struct sockaddr
{
unsigned short sa_family;
char sa_data[14];
};
struct sockaddr_in
{
short int sin_family;
unsigned short int sin_port;
struct in_addr sin_addr;
unsigned char sin_zero[8];
};
struct in_addr
{
unsigned long s_addr;
};
struct in6_addr
{
uint8_t s6_addr[16]; /ipv6 address/
};
struct sockaddr_in6
{
short int sin6_family; /AF_INET6/
unsigned short int sin6_port; /transport layer port #/
uint32_t sin6_flowinfo; /ipv6 traffic class & flow info/
struct in6_addr sin6_addr; /ipv6 address/
uint32_t sin6_scope_id; /set of interfaces for a scope/
}
sin_family指代协议族,在socket编程中只能是AF_INET
sin_port存储端口号(使用网络字节顺序)
sin_addr存储IP地址,使用in_addr这个数据结构,s_addr按照网络字节顺序存储IP地址
sin_zero是为了让sockaddr与sockaddr_in两个数据结构保持大小相同而保留的空字节。
sockaddr_in和sockaddr是并列的结构,指向sockaddr_in的结构体的指针也可以指向
sockadd的结构体,并代替它。也就是说,你可以使用sockaddr_in建立你所需要的信息,
在最后用进行类型转换就可以了bzero((char*)&mysock,sizeof(mysock));//初始化
二、地址转换
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
2.1 IP地址形式
210.25.132.181 是字符串形式的IP地址;3524887733是整数形式的IP地址
2.2 地址转换函数
2.2.1 字符串-->整数形式
inet_addr、inet_network 和inet_aton都是将一个字符串IP地址转换成整数形式;
区别1:inet_addr和inet_aton转换后的整数是网络字节序;
inet_network转换后的整数是主机字节序;
区别2:inet_addr和inet_network将255.255.255.255作为无效的IP地址
inet_aton将255.255.255.255作为有效的IP地址(大多数路由器认为255.255.255.255是有效地址)
in_addr_t inet_addr (const char *cp); //cp是一个点分十进制的IP地址,返回值unsigned long(网络字节序)
in_addr_t inet_network(const char *cp); //cp是一个点分十进制的IP地址,返回值unsigned long(主机字节序)
int inet_aton(const char *string, struct in_addr*addr);//string是一个点分十进制的IP地址,转换后的IP地址放在addr(网络字节序)中
2.2.2 整数形式-->字符串
char *inet_ntoa(unsigned in_addr addr);//addr是主机字节序,此函数的返回值会被下次调用返回值覆盖
in_addr_t inet_lnaof(struct in_addr in);//获取in(网络序)地址的主机ID(主机序)
in_addr_t inet_netof(struct in_addr_in);//获取in(网络序)地址的网络ID(主机序)
struct in_addr inet_makeaddr(int net, int host);//将net是网络ID,host主机ID合并为一个新的IP地址
2.2.3 扩展函数
int inet_pton(int af, const char *src, void *dst);
“点分十进制”-->二进制整数
af:地址族 AF_INET 或者 AF_INET6
src:点分十进制字符串
dst:转换后的二进制整数存储在dst中
返回值:成功1,参数无效0,错误-1
const char *inet_ntop(int af, const void *src, char *dst, int dstbuff_len);
二进制整数-->“点分十进制”
af:地址族 AF_INET 或者 AF_INET6
src:二进制整数
dst:转换后的点分十进制字符串
dstbuff_len: 缓存区dst的大小,避免溢出,如果缓存区太小去发存储地址的值,返回空指针,errno置为ENOSPC。
返回值:成功返回字符串首地址,错误返回NULL
三、主机序和网络序的转换
数据:0x010203
大端模式,在内存中的存储顺序:
0x4000 0x4001 0x4002
01 02 03
小端模式,在内存中的存储顺序:
0x4000 0x4001 0x4002
03 02 01
网络字节序采用大端模式;
uint16_t htons(uint16_t hostshort) 主机序到网络序
uint32_t htonl(uint32_t hostlong)
uint16_t ntohs(uint16_t netshort) 网络序到主机序
uint32_t ntohl(uint32_t netlong)