思想:创建多个套接字,由"我"来管理这些套接字
方法:
1.多进程
2.多线程
3.IO多路复用
tcp服务器端创建流程:
socket()
bind()
listen()
connfd = accept
IO多路复用:
多个文件I复用同一个进程
IO模型
IO模型
1.阻塞IO
fgets scanf read recv gerchar
2.非阻塞IO
1.使用轮询的方式实现,可以监测多路IO
2.cpu占有率较高
实现:
1.获取原文件描述符的属性
fcntl();
F_GETFL;
2.增加非阻新属性
3.设置新属性
3.信号驱动IO
1.异步通知的io方式,节省cpu
4.IO多路复用
1.多个IO复用一个进程(谁的文件描述符到达了,就进行那个文件描述符关联的文件的读写操作)
2.不适合处理比较耗时的任务
内核提供的IO多路复用接口:
select
poll
epoll
处理流程:
1.创建一个需要关注的文件描述符的集合
2.添加文件描述符到集合中
3.通知内核开始监测
4.根据监测返回的结果做对应的操作(对IO的读/写操作)
管道文件、系统文件、文件描述符等
select :
Int select(int nfds, fd_ set * readfds, fd_set * wirtefds, fd_set *exceptfds,struct timeval * timeout)
功能:监测多路IO
参数:
readfds:关注的读事件的文件描述符集合
writefds:关注的写事件的文件描述符集合
exceptfds:其他 异常
timeout:超时时间 如果不设置就写NULL
返回值:
成功:返回到达事件的个数
失败:-1
设置了超时时间:超时时间到达,但没有事件,返回0
在Linux下,文件描述符的分配遵循最小未被分配原则。
比如你已经分配了fd,则下一个文件描述符一定比fd大
Linux中就只有1024个文件描述符
1.select缺点:
1.select监听文件描述符最大个数为1024(数组)0 (n)不
2.select监听的文件描述符集合在用户层,需要应用层和内核层互相传递数据
3.select需要循环遍历一次才能找到产生的事件
4.select只能工作在水平触发模式(低速模式)无法工作在边沿触发模式(高速模式)
poll缺点:
1.po11监测文件描述符不受上限限制(链表)0(n
2.po11监听的文件描述符集合在用户层,需要内核层向用户层传递数据
3.po11需要循环遍历一次才能找到产生的事件
4.po11只能工作在水平触发模式(低速模式)无法工作在边沿触发模式(高速模式)
epoll
将检测的文件描述符由链表改为红黑树(查找效率更高)
时间复杂度:用来衡量某个程序的效率
红黑树---->二叉树 时间复杂度(logn)
优点:
1.epol1创建内核事件表,不受到文件描述符上限限制(红黑树) 0(logn
2.epoll监听的事件表在内核中,直接在内核中监测事件效率高
3.epo11会直接获得产生事件的文件描述符的信息,而不需要遍历检测
4.epol1既能工作在水平触发模式,也能工作在边沿触发模式
epoll使用步骤:
1.创建文件描述符集合
因为是内核创建,所以要调用一个函数接口,通知内核创建集合
int epoll_create
#include <sys/epoll.h>
int epoll_create(int size);
参数:
告诉内核大概放多少个文件描述符
返回值:
成功:返回一个文件描述符(集合句柄)
失败:-1
2.添加文件描述符到集合中 epoll_ctl
#include <sys/epoll.h>
int epoll_ctl(int epfd, int op, int fd, struct
epoll_event *event);
参数:
epfd:文件描述符集合句柄
op:操作
EPOLL_CTL_ADD:向集合中添加文件描述符
EPOLL_CTL_MOD:修改集合
EPOLL_CTL_DEL:删除
fd:操作的文件描述符
event:文件描述符所对应的事件
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 member:
3.通知内核开始监测: epoll_wait
#include <sys/epoll.h>
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);
参数:
epfd:文件描述符集合句柄
events:保存到达事件的集合的首地址
maxevents:监测的事件的个数
timeout:超时时间
-1:不设置超时时间
返回值:
成功:返回到达事件的个数
失败:-1
设置超时:超时时间到达则返回0