c++学习

自由方向 / 2023-07-27 / 原文

下面的内容都是在linux环境下。

网络I/O

  有阻塞IO,非阻塞IO,IO多路复用,信号驱动IO和异步IO五种方式。

1.阻塞非阻塞

  阻塞与非阻塞针对的是数据就绪阶段,如果是阻塞,则程序将一直等待,知道数据就绪,然后开始读取,如果是非阻塞,则若数据还未就绪,程序可以先执行别的事务,但是I/O还是要处理,所以这里一般会设置一个循环,通过轮询的方式不断检测数据是否就绪。(这里一般是用read或者recv等函数,为文件描述符的flag或上一个O_NONBLOCK标志位来设置非阻塞,默认阻塞,设置为阻塞时,数据未就绪则阻塞在函数位置,设置为非阻塞时,数据未就绪则返回-1和error标志。)

2.同步异步

  同步异步看的是在等待数据就绪或者执行数据读取时,程序是否能执行别的操作,对于read或者recv等函数,在读取时程序不能执行其他操作,所以是同步(阻塞IO,非阻塞IO,IO多路复用,信号驱动IO都是这种),而异步IO在调用aio_read()和aio_write()这种异步接口后,便可以执行其他操作,内核在检测到数据读取完成后发送一个信号通知程序,其实这里如果异步IO没有设置为非阻塞,则在数据就绪阶段也不算异步,所以一般都是异步非阻塞。

3.IO多路复用

  实现IO多路复用可以使用select,poll和epoll函数,epoll函数包括LT和ET两种工作模式,需要注意的是,ET模式要求一次性读完所有数据,因为ET模式除了在数据就绪之后会发送通知,后续不会再通知,如果接收区域不够大,可以设置一个循环,直到读取完毕,但是这时候要设置为非阻塞,否则在读取完后便会阻塞在read函数处,无法跳出循环。