介绍了socket和套接字地址,以及两者关系(一个socket需要与一个套接字地址绑定);介绍了两个与之相关的结构体socketaddr和socketaddr_in。
目录
一.套接字,两个重要的结构体
我们知道,计算机网络通信的主体是进程(process)。对于计算机网络中的某一台主机上的某一个进程,我们可以使用套接字唯一标识。套接字(socket)由本机的IP地址和该进程的port号确定,即socket = ip address + port number,用于唯一标识一个进程。
计算机网络上的点对点通信需要两个套接字,即套接字对(socket pair)= [host ip add, host port number, remote ip add, remote port number],其标识了一个通信过程。但是需要注意的时,单独的套接字不依赖通信过程而存在。
我们知道,对于计算机网络而言,套接字对模型像是一根连接通信双方的管道。那么Linux OS是怎么具体实现套接字(socket)的呢? 我们知道,在Linux OS中,一切皆文件。socket也是被认为是一个文件,Linux为其分配了一个文件描述符sfd,和两个缓冲区(一个input buffer,另一个output buffer,全两者均用sfd标识)。
一台主机上同时可能有多个进程参与网络通信,所以需要为其分配不同的套接字来区分它们,这就是套接字地址(理解为套接字的值即可)。关于套接字地址我们有两个重要的结构体。
二.socketaddr和socketaddr_in
两者的定义分别为:
struct sockaddr {
unsigned short sa_family; /* 地址族, AF_xxx */
char sa_data[14]; /* 14字节的协议地址*/
};
struct sockaddr_in {
sa_family_t sin_family; /* address family: AF_INET */
in_port_t sin_port; /* port in network byte order */
struct in_addr sin_addr; /* internet address */
};
/* Internet address. */
struct in_addr {
uint32_t s_addr; /* address in network byte order */
};
socketaddr和socketaddr_in类型的数据均可视为套接字地址。 直接供我们使用的是socketaddr_in,因为其三个成员分别容纳协议类型(sin_familiy, int类型),端口号(sin_port uint16_t类型),IP地址(in_addr这个结构体的成员s_addr,uint32_t类型)。注意,其所需的端口号和IP地址均要求网络字节序。
不过,作为一些重要的系统调用(比如bind函数,accept函数等等)的参数的套接字地址均为socketaddr型。所以,需要对socketaddr_in进行强制类型转换。
//以下是对socketaddr_in的使用
socketaddr_in addr;//声明一个套接字地址
addr.sin_family = AF_INET;//给定协议族
addr.sin_port = htons(2050);//给定端口号
int dst;//用于存放IP地址的数值、网络字节序形式
inet_pton(AF_INET,"192.55.0.2",&dst);
addr.sin_addr.s_addr = dst;