一、TCP并发服务器模型之多线程
- 作用:解决TCP并发问题。
- 局限:线程会占用独立栈空间,可同时创建的线程数量有限;并发客户端数量过多时,系统存在崩溃风险。
- 工程使用:一般搭配线程池(线程管理机制)一起使用。
二、4种常见IO模型
1. 阻塞IO
- 效率高。没有数据到达时,CPU将任务挂起,该任务不占用CPU资源。
2. 非阻塞IO
- 效率低。没有数据的时候,CPU仍然会在该任务中执行代码,轮询检测数据是否到来。
3. 信号驱动IO(异步IO)
- 将文件描述符设置为异步IO,并且指定异步IO通知进程对象。
- 内核监测文件描述符是否发生事件;事件产生后通知用户层。
- 用户层捕捉
SIGIO信号,处理对应文件描述符上的事件。
4. 多路复用IO
select
select监听文件描述符集合。当集合中至少一个文件描述符产生事件,select解除阻塞;会保留发生事件的fd,把没有事件的fd从集合中清除。
select配套宏函数
// 将fd从集合清除
void FD_CLR(int fd, fd_set *set);
// 判断fd是否还在集合中
int FD_ISSET(int fd, fd_set *set);
// 将fd加入集合
void FD_SET(int fd, fd_set *set);
// 将集合全部清零
void FD_ZERO(fd_set *set);
select函数原型
int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);
功能:监听文件描述符集合内是否产生事件。
参数
nfds:最大文件描述符的值 + 1readfds:读文件描述符集合writefds:写文件描述符集合exceptfds:异常文件描述符集合timeout:超时时间;传入NULL代表阻塞等待
返回值
- 成功:返回产生事件的文件描述符数量
- 失败:返回
‑1 - 超时时间到,无事件:返回
0
三、epoll多路复用API
1. epoll_create
int epoll_create(int size);
功能:创建内核监听事件表。
参数
size:事件表中事件个数,该参数现已被忽略。
返回值
- 成功:返回epoll对应的文件描述符
- 失败:返回
‑1
2. epoll_ctl
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
功能:操作epoll内核事件表。
参数
epfd:epoll事件表的文件描述符op:操作类型EPOLL_CTL_ADD:向事件表添加事件EPOLL_CTL_MOD:修改事件表内事件EPOLL_CTL_DEL:从事件表删除事件
fd:待操作的文件描述符event:与fd绑定的事件
返回值
- 成功返回
0 - 失败返回
‑1
相关结构体
typedef union epoll_data {
void *ptr;
int fd;
uint32_t u32;
uint64_t u64;
} epoll_data_t;
struct epoll_event {
uint32_t events; /* Epoll events */
epoll_data_t data; /* User data variable */
};
事件宏:
EPOLL_IN:可读事件EPOLL_OUT:可写事件EPOLLET:设置为边沿触发模式,默认水平触发
3. epoll_wait
int epoll_wait(int epfd, struct epoll_event *events,
int maxevents, int timeout);
功能:监听事件表中的事件是否发生。
参数
epfd:epoll文件描述符events:存放触发事件数组的首地址maxevents:events数组的大小timeout:超时时间;传入‑1代表阻塞直到事件发生
返回值
- 成功:返回触发事件的文件描述符个数
- 失败:返回
‑1 - 超时无事件:返回
0