IP地址和端口号
IPV4
:4
字节地址族
IPV6
:16
字节地址族
先查询网络地址,再查询主机地址。
A类地址的首字节范围: 0–127,A类地址的首位以0开始
B类地址的首字节范围: 128–191 ,B类地址的前2位以10开始
C类地址的首字节范围: 192–223 ,C类地址的前3位以110开始
端口号:可分配0~65535
,但0~1023
是知名端口。
UDP
和TCP
可以用同一个端口号,因为他们不共用。
地址信息的表示
struct sockaddr_in{
sa_family_t sin_family;//地址族
uint16_t sin_port;//16位TCP/UDP端口号
struct in_addr sin_addr;//32位IP地址。
}
struct in_addr{
in_addr_t s_addr;//32位IP地址。
}
成员sin_family
:
成员sin_port
:
保存端口号,并且是以网络字节序保存的。
成员sin_addr
:
保存32
位IP
地址,也是以网络字节序保存的。
成员sin_zero
:
为了大小和sockaddr
保持一致。
bind(serv_sock,(struct sockaddr *)&serv_addr,sizeof(serv_addr))
,期待的是sockaddr
结构体,但是它长这样:
struct sockaddr{
sa_family sin_family;
char sa_data[14];//地址信息:IP+端口号
}
为了方便我们直接转换就可以了。
网络字节序和地址变换
cpu
有2
种方式解析数据,大端序、小端序(高位字节放到低/高位地址),传输的时候都转换成大端序。
字符串信息(127.0.0.1
)转换成网络字节序:
in_addr_ t inet_addr(const char * string);
,成功返回32
位大端序整数型值,失败时返回INADDR_NONE
.
或者使用int inet_aton(const char * string,struct in_addr * addr);
,成功返回1
,失败返回0
,自动传进结构体里。
反向操作:char* inet_ntoa(struct in_addr adr);
,网络字节序转IP
地址。但是会用到同一块空间,所以需要把内容复制出来。
网络地址信息初始化
每次创建服务端套接字会有点繁琐,直接使用htonl(INADDR_ANY)
,自动分配服务器的IP
地址(常数),对于多宿主(多个IP
)也会比较方便。