IO 多路复用
# 1. 基础概念
# 1.1 Socket
套接字。百科:对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。
例子:客户端将数据通过网线发送到服务端,客户端发送数据需要一个出口,服务端接收数据需要一个入口,这两个“口子”就是 Socket。
# 1.2 FD: File Descriptor
文件描述符,非负整数。“一切皆文件”,linux 中的一切资源都可以通过文件的方式访问和管理。而 FD 就类似文件的索引(符号、指针),指向某个资源,内核(kernel)利用 FD 来访问和管理资源。
当我们调用内核函数创建 socket 后,内核返回给我们的是 socket 对应的文件描述符(fd),所以我们对 socket 的操作基本都是通过 fd 来进行。
# 1.3 Socket 通信
我们通过一张图来看下客户端和服务器使用 socket 进行通信的核心流程:
图中函数的含义如下:
socket:创建一个套接字
bind:将 socket 绑定到指定地址
listen:使套接字处于监听状态,等待客户端连接到来
accept:接受客户端连接
connect:客户端发起连接
read:从 fd 对应的 socket 中读取数据
write:将数据写入 fd 对应的 socket 中
close:关闭 socket 文件描述符
# 1.4 IO 模型小栗子
接着我们通过一个例子来了解下各种IO模型。
例子:你是一个老师,让学生做作业,学生做完作业后收作业。
- **同步阻塞:**逐个收作业,先收A,再收B,接着是C、D,如果有一个学生还未做完,则你会等到他写完,然后才继续收下一个。
- 解析:这就是同步阻塞的特点,只要中间有一个未就绪,则你会被阻塞住,从而影响到后面的其他学生。
- **同步非阻塞:**逐个收作业,先收A,再收B,接着是C、D,如果有一个学生还未做完,则你会跳过该学生,继续去收下一个。
- 解析:可以看到同步非阻塞相较于同步阻塞已经是更好的方案了,你不会因为某个学生未就绪而阻塞住,这样就可以减少对后续学生的影响。但是这个方案也可能会出现其他问题,如果你下去收作业的时候,全部学生都还没做完,则你可能会白走一圈,然后一个作业也没收到。
- **select/poll:**学生写完了作业会举手,但是你不知道是谁举手,需要一个个的去询问。
- 解析:这个方案相较于同步非阻塞来说有一点好处,就是你是确认有学生做完的,所以你下去肯定能收到作业,但是他有一个不好的点在于你需要一个个的去询问。
- **epoll:**学生写完了作业会举手,你知道是谁举手,你直接去收作业。
- 解析:这个方案就很高效了,每次都能准确的收到作业。
编辑 (opens new window)
上次更新: 2023/01/03, 05:28:25