套接字和地址
导学问题:
1、 IPv4、IPv6、本地套接字格式以及通用地址套接字有什么共性?
2、为什么IPv4 和 IPv6 套接字需要绑定端口号,而本地套接字不用?
socket套接字
socket套接字的本质是一个特殊的文件描述符,通过这个文件描述符,我们可以进行数据的收发,如下图:
里面的通信细节我们暂时不用关注,了解套接字的角色即可。
socket 的发展历史
加州大学伯克利分校(BSD)的研究人员,在 20 世纪 80 年代早期提出来了socket套接字,它的设计思想融合了unix一切皆文件的哲学理念,底层协议是TCP/IP,由于其简洁高效的特性,很快就流行开来了。Linux 作为 Unix 系统的一个开源实现,很早就从头开发实现了 TCP/IP 协议,伴随着socket 的成功,Windows 也引入了 socket 的概念。于是在今天的世界里,socket 成为网络互联互通的标准。
套接字格式
通用套接字:
struct sockaddr{ sa_family_t sa_family; /* 地址族. 16-bit*/ char sa_data[14]; /* 具体的地址值 112-bit */ };
IPv4 套接字:
struct sockaddr_in { sa_family_t sin_family; /* 地址族. 16-bit*/ in_port_t sin_port; /* 端口口 16-bit*/ struct in_addr sin_addr; /* 这里仅仅用作占位符,不做实际用处 */ unsigned char sin_zero[8]; };
IPv6 套接字:
struct sockaddr_in6 { sa_family_t sin6_family; /* 地址族. 16-bit*/ in_port_t sin6_port; /* 传输端口号 # 16-bit */ uint32_t sin6_flowinfo; /* IPv6流控信息 32-bit*/ struct in6_addr sin6_addr; /* IPv6地址128-bit */ uint32_t sin6_scope_id; /* IPv6域ID 32-bit */ };
从上面我们可以看到,IPv4和IPv6的套接字地址格式是不一样的,因此我们如果想要对两者进行抽象统一,就必须要构造一个通用套接字地址格式。有了统一可以操作的地址结构,那么就可以设计一套统一的接口。结合强制类型转换,也能预防内存泄露
对于地址族,有非常多类型,这里只列举常见的几种:
-
AF_LOCAL:表示本地通信,很多人对网络通信存在误解,以为socket接口只能用在不同主机间通信,实际上它也可以用于本机进程间通信的。很多情况下,也可以写成AF_UNIX、AF_FILE
-
AF_INET:因特网使用的IPv4地址
-
AF_INET6:因特网使用的IPv6地址
注意:有时候AF_XXX也会被写成PF_XXX,这两个实际是同一个宏。
sin_port表示端口号,用来区分主机中进程 sin_addr表示ip地址,用来表示本机在网络中的编号
总结
文章重点介绍了不同类型套接字地址之间的一些区别,并对它们存在的这些区别的原因进行了讲解,再结合下面这一幅图,就能很清晰地掌握不同类型的套接字地址了,如下图: