一、什么是socket
socket可以看成是用户进程与内核网络协议栈的编程接口。
socket不仅可以用于本机的进程间通信,还可以用于网络上不同主机的进程间通信。
socket API是一层抽象的网络编程接口,适用于各种底层网络协议,如IPv4、IPv6,以及以后要讲的UNIX Domain Socket。然而,各种网络协议的地址格式并不相同,如下图所示:
IPv4和IPv6的地址格式定义在netinet/in.h中,IPv4地址用sockaddr_in结构体表示,包括16位端口号和32位IP地址,如下所示:
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 */
char sin_zero[8]; /* pad bytes, set to zero is ok */
};
/* Internet address. */
struct in_addr {
uint32_t s_addr; /* address in network byte order */
};
IPv6地址用sockaddr_in6结构体表示,包括16位端口号、128位IP地址和一些控制字段。UNIX Domain Socket的地址格式定义在sys/un.h中,用
sockaddr_un结构体表示。各种socket地址结构体的开头都是相同的,对于unix 的某些实现来说 前8位表示整个结构体的长度,后8位表示地址类型,
而Linux就没有长度字段,前2个字节都是地址类型。IPv4、IPv6和UNIX Domain Socket的地址类型分别定义为常数AF_INET、AF_INET6、
AF_UNIX。 这样,只要取得某种sockaddr 结构体的首地址,不需要知道具体是哪种类型的sockaddr 结构体,就可以根据地址类型字段确定结构体中
的内容。因此,socket API可以接受各种类型的 sockaddr结构体指针做参数,例如bind、accept、connect等函数,这些函数的参数应该设计成void *
类型以便接受各种类型的指针,但是sock API的实现早于ANSI C标准化,那时还没有void *类型,因此这些函数的参数都用struct sockaddr *类型表