1、套接字构成
套接字=IP地址+端口号
2、地址信息的表示
应用程序中使用的IP地址和端口号以结构体的形式给出了定义。 此结构体将作为地址信息传递给bindhans函数。
struct sockaddr_in
{
sa_family_t sin_family; //地址簇
unit_16_t sin_port; //端口号
struct in_addr sin_addr; //IP地址
char sin_zero[8]; //不使用
};
struct in_addr
{
In_addr_t s_addr; //32位IPv4地址
};
sin_family存放dizh地址簇信息,每种xiey协议簇适用的地址簇均不同,AF_INET表示IPv4协议中使用的地址簇,AF_INET6表示IPv6协议中使用的地址簇,AF_LOCAL表示本地通信中采用的地址簇。
sin_port保存16位端口号,重点在于它以网络字节序保存。
sin_addr保存32位IP地址信息,也以网络字节序保存。
sin_zero无特殊意义,必须填充为0。
3、网络地址序与地址变换
存储字节序:一个多字节的变量在内存中的存储方式,变量的小端数据存储在内存起始位置是小端字节序;变量的大端数据存储在内存起始位置是大端字节序;
传输字节序:协议传输多字节变量时的传输方式,先传输大端字节的方式成为大端字节序;先传输小端字节的方式成为小端字节;网络协议使用大端字节序传输数据,USB协议使用小端字节序传输协议;
两者关系:由于系统主机存在大小端模式,并且不能保证网络通信的两个主机之间的存储字节序一致,所以网络协议就规定自身在传输数据的时候使用的字节序为大端字节序,这样网络通信的双方主机就会达成一致,对接收到的数据(大端模式)依据自身的存储字节序来进行处理;存储字节序和传输字节序本质上是一样的概念;
#include <netinet/in.h>
uint16_t htons(uint16_t host16bitvalue) //返回网络字节序的值
uint32_t htonl(uint32_t host32bitvalue) //返回网络字节序的值
uint16_t ntohs(uint16_t net16bitvalue) //返回主机字节序的值
uint32_t ntohl(uint32_t net32bitvalue) //返回主机字节序的值
上述函数中,h代表host,n代表network,s代表short,l代表short;
当使用这些函数时,我们并不关心主机字节序和网络字节序的真实值,只要调用适当的函数在主机和网络字节序之间转换某个给定的值。
INADDR_ANY
每次创建服务器端套接字都要输入IP地址有些繁琐,此时可以如下初始化地址信息。服务器中优先考虑这种方式,而客户端中除非带有一部分服务器端功能,否则不会采用。
addr.sin_addr.s_addr = htonl(INADDR_ANY);
4、创建过程
int serv_sock;
struct sockaddr_in ser_addr;
char *serv_port = "9190";
//创建套接字
serv_sock = socket(PF_INET, SOCK_STREAM, 0);
//地址信息初始化
memset(&ser_addr, 0, sizeof(ser_addr));
ser_addr.sin_family = AF_INET;
ser_addr.sin_addr.s_addr = htonl(INADDR_ANY);
ser_addr.sin_port = htonl(atoi(serv_port));
//分配地址信息
bind(serv_sock, (struct sockaddr*)&ser_addr, sizeof(ser_addr));