TCP并发服务器
单循环服务器:一次只能处理一个客户端任务的服务器。
并发服务器:能够同时处理多个客户端任务的服务器。(一对多)
- UDP服务端:具备并发性能
- TCP服务端:建立连接,单循环服务器
TCP并发服务端四种实现方案
-
多进程 安全、资源开销大、并发量小
-
多线程 相对进程资源开销小,相对并发量大
-
线程池 多线程模型。提前创建好大量线程管理起来,避免反复创建线程带来时间消耗
生产者--消费者 设计模式 主线程负责生产,线程池负责执行任务 任务队列
-
IO多路复用 在不创建新进程/线程的前提下,使用一个进程同时监测多路IO
文件 ---》fd 对多个文件描述符的监测,复用一个进程。 实现接口:
select、poll、Epoll
多进程伪代码
Socket();
Bind();
Listen();
While(1)
{
Int connfd=accept();
Pid_t pid=fork();
If(pid>0)
{
}
Else if(pid==0)
{
While(1)
{
Recv();
Send();
}
}
}
多线程伪代码
Socket();
Bind();
Listen();
While(1)
{
Int connfd=accept();
Pthread_create();
Pthread_datach();//分离属性
}
IO多路复用
在一个进程中,同时监测多个IO
select、poll、epoll
select
1)创建文件描述符集合(位图(数组)----》1024)
fd_set fds; FD_ZERO(&fds);2)将要监测的文件描述符加入集合
FD_SET(fd,&fds);3)将集合传递给内核开始监测IO事件,并返回监测的结果
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
select函数
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
功能:通知内核监测文件描述符中的事件,并返回检测到的结果
参数
- nfds :集合中最大的文件描述符+1
- readfds:读事件的文件描述符集合
- writefds:写事件的文件描述符集合
- exceptfds:出错事件的文件描述符集合
- timeout:超时时间
NULL:不设置超时时间(阻塞等待)返回值
- 成功:返回到达IO事件的个数
- 失败:
-10:设置了超时时间,超时了还没有事件到达
配套宏函数
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);
//功能:将集合表中的fd对应的文件描述符加进去
void FD_ZERO(fd_set *set);
//功能:将集合表全部清零
select特点
- 使用数组(位图)保存文件描述符集合,最多允许监测1024个文件描述符;
- 将集合表创建在应用层,需要应用层和内核层的反复数据拷贝;
- 需要遍历寻找到达的IO事件,效率低;
- 只能工作在水平触发模式(低速模式),不能工作在边沿触发模式(高速模式);
poll特点
- 使用链表保存文件描述符集合,允许监测的文件描述符没有上限限制;
- 将集合表创建在应用层,需要应用层和内核层的反复数据拷贝;
- 需要遍历寻找到达的IO事件,效率低;
- 只能工作在水平触发模式(低速模式),不能工作在边沿触发模式(高速模式);
epoll特点
- 使用树形结构保存文件描述符集合(红黑树),允许监测的文件描述符没有上限限制,并且查找效率高;
- 将集合表直接创建在内核层,避免应用层和内核层的反复数据拷贝;
- 直接返回到达的事件,不需要应用层遍历查找;
- 可以工作在水平触发模式(低速模式),也可以工作在边沿触发模式(高速模式);
epoll使用步骤
- 创建文件描述符集合
- 添加文件描述符到集合
- 通知内核开始监测事件
epoll_create
int epoll_create(int size);
功能 :创建文件描述符集合 参数
- size:监测的文件描述符的最大上限 返回值
- 成功:返回集合代表的文件描述符(句柄)
- 失败:
-1
epoll_ctl
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
功能 :对epoll的文件描述符集合进行操作 参数
- epfd:文件描述符集合
- op:操作指令
EPOLL_CTL_ADD:添加EPOLL_CTL_MOD:修改EPOLL_CTL_DEL:删除- fd:需要操作的文件描述符
- event:事件类型 返回值
- 成功:
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 */
};
events:事件类型
EPOLLIN:读事件EPOLLOUT:写事件
epoll_wait
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);
功能 :通知内核开始监测文件描述符集合并等待返回监测到的事件结果 参数
- epfd:文件描述符集合
- events:保存到达事件的集合
- maxevents:监测的事件最大个数
- timeout :超时时间
-1:不设置超时,一直阻塞等待返回值
- 成功:返回到达事件的个数
- 失败:
-10:超时时间到达,却没有事件返回
IO多路复用的应用场景
