Socket
Socket
介绍
前面提到的管道、消息队列、共享内存、信号量和信号都是在同一台主机上进行进程间通信,那要想 跨网络与不同主机上的进程之间通信,就需要 Socket 通信了。
实际上,Socket 通信不仅可以跨网络与不同主机的进程间通信,还可以在同主机上进程间通信。
系统调用使用
我们来看看创建 socket 的系统调用:
/**
* @param domain 用来指定协议族。比如:
* - AF_INET 用于 IPV4
* - AF_INET6 用于 IPV6
* - AF_LOCAL/AF_UNIX 用于本机;
*
* @param type 用来指定通信特性。比如:
* - SOCK_STREAM 表示的是字节流,对应 TCP、
* - SOCK_DGRAM 表示的是数据报,对应 UDP、SOCK_RAW 表示的是原始套接字;
*
* @param protocal 原本是用来指定通信协议的,但现在基本废弃。
* 因为协议已经通过前面两个参数指定完成,protocol 目前一般写成 0 即可;
*/
int socket(int domain, int type, int protocal)
Socket 类型
根据创建 socket 类型的不同,通信的方式也就不同:
- 实现 TCP 字节流通信: socket 类型是 AF_INET 和 SOCK_STREAM;
- 实现 UDP 数据报通信:socket 类型是 AF_INET 和 SOCK_DGRAM;
- 实现本地进程间通信:
- 「本地字节流 socket 」类型是 AF_LOCAL 和 SOCK_STREAM
- 「本地数据报 socket 」类型是 AF_LOCAL 和 SOCK_DGRAM
- 另外,AF_UNIX 和 AF_LOCAL 是等价的,所以 AF_UNIX 也属于本地 socket;
三种Socket类型
接下来,简单说一下这三种通信的编程模式。
针对 TCP 协议通信的 socket 编程模型
流程:
- 准备及连接阶段
- 服务端和客户端初始化
socket
,得到文件描述符; - 服务端调用
bind
,将绑定在 IP 地址和端口; - 服务端调用
listen
,进行监听; - 服务端调用
accept
,等待客户端连接; - 客户端调用
connect
,向服务器端的地址和端口发起连接请求; - 服务端
accept
返回用于传输的socket
的文件描述符;
- 服务端和客户端初始化
- 通信阶段
- 客户端调用
write
写入数据;服务端调用read
读取数据;
- 客户端调用
- 断开阶段
- 客户端断开连接时,会调用
close
。那么服务端read
读取数据的时候,就会读取到了EOF
,待处理完数据后,服务端调用close
,表示连接关闭。
- 客户端断开连接时,会调用
这里需要注意的是,服务端调用 accept
时,连接成功了会返回一个已完成连接的 socket,后续用来传输数据。
所以,监听的 socket 和真正用来传送数据的 socket,是「两个」 socket:
- 一个叫作 监听 socket;
- 一个叫作 已完成连接 socket。
成功连接建立之后,双方开始通过 read 和 write 函数来读写数据,就像往一个文件流里面写东西一样。
针对 UDP 协议通信的 socket 编程模型
UDP 是没有连接的,所以不需要三次握手,也就不需要像 TCP 调用 listen 和 connect,但是 UDP 的交互仍然需要 IP 地址和端口号,因此也需要 bind。
对于 UDP 来说,不需要要维护连接,那么也就没有所谓的发送方和接收方,甚至都不存在客户端和服务端的概念,只要有一个 socket 多台机器就可以任意通信,因此每一个 UDP 的 socket 都需要 bind。
另外,每次通信时,调用 sendto 和 recvfrom,都要传入目标主机的 IP 地址和端口。
针对本地进程间通信的 socket 编程模型
本地 socket 被用于在同一台主机上进程间通信的场景:
- 本地 socket 的编程接口和 IPv4 、IPv6 套接字编程接口是一致的,可以支持「字节流」和「数据报」两种协议;
- 本地 socket 的实现效率大大高于 IPv4 和 IPv6 的字节流、数据报 socket 实现;
对于本地字节流 socket,其 socket 类型是 AF_LOCAL 和 SOCK_STREAM。
对于本地数据报 socket,其 socket 类型是 AF_LOCAL 和 SOCK_DGRAM。
总结
区别:本地字节流 socket 和 本地数据报 socket 在 bind 的时候,不像 TCP 和 UDP 要绑定 IP 地址和端口,而是绑定一个本地文件,这也就是它们之间的最大区别。