思考:为什么线程开销会大
一、IO 有两种操作,同步 IO 和异步 IO 。
同步 IO 指的是,必须等待 IO 操作完成后,控制权
才返回给用户进程 。
异步 IO 指的是,无须等待 IO 操作完成,就将控制权返回给用户进程。
网络中的 IO ,由于不同的 IO 设备有着不同的特点,网络通信中往往需要等待 。 常见的
有以下 4 种情况 。
(1)、输入操作
(2)、输出操作
(3)、服务器接收连接请求
(4)、客户端发送连接请求
2、四种网络IO模型
阻塞是指 IO 操作需要彻底完成后才返回到用户空间;
而非阻塞是指 IO 操作被调用后立即返回给用户一个状态值,
不需要等到 IO 操作彻底完成
(1)、阻塞IO模型
只有系统调用获得结果或者超时出错才返回结果
(2)、非阻塞IO模型
从用户进程角度讲,它发起一个 read操作后,并不需要等待,而是马上就得到了
一个结果 。 当用户进程判断结果是一个错误时,它就知道数据还没有准备好,于是它可以
再次发送 read 操作,在非阻塞式 IO 中,用户进程其实需要不断地主动询问kernel 数据是
否准备好。非阻塞的接口相比于阻塞型接口的显著差异在于被调用之后立即返回 。
使用如下的函数可以将某句柄归设为非阻塞状态 :fcntl( fd , F_SETFL , O_NONBLOCK );
缺点;循环调用recv()会很消耗CPU
(3)、多路复用IO
基本原理:就是有个函数(如select)会不断地轮询所负责的所有 socket,当某个
socket 有数据到达了,就通知用户进程,
(4)、异步IO模型(后面具体来说)
三、select
1、函数原型
#include <sys/select.h>
int select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,struct timeval *timeout);
maxfdp 一个整数值,指的是集合中所有文件描述符的范围,即文件描述符数量+1
readfds,writefds,errorfds 都应该包括文件描述符
timeout 超时时间
2、重要的宏
void FD_ZERO(int fd, fd_set *fdset); // 关闭描述字集上的所有位
void FD_SET(int fd, fd_set *fd_set);// 打开描述字集上一个描述符位
void FD_CLR(int fd, fd_set *fdset); // 关闭描述字集上一个描述符位
int FD_ISSET(int fd, fd_set *fdset); // 判断描述符位是否在描述字集上
(1) FD_ZERO宏,初始化,将一个 fd_set类型变量的所有位都设为 0