网络编程(三)

IO复用

IO即为网络网络 I/O,多路即为多个tcp连接,复用即为共用一个线程或者进程,模型最大的优势是系统开销小,不必创建也不必维护过多的线程或者进程。
IO多路复用,最主要是服务器同时可以处理监听套接字和连接套接字 可以不用多创建一个线程和进程 直接用io复用提高程序的效率

select

select最多可以监听1024个fd。select采取轮询+遍历的方式。select具有很好的跨平台性。
当client连接到server后,server会创建一个该连接的描述符fd,fd有三种状态,分别是读、写、异常,存放在三个fd_set(其实就是三个long型数组)中。select本质是通过设置和检查fd的三个fd_set来进行下一步操作。

执行步骤

  • 通过select将read、write、except的文件描述符传入内核
  • 内核遍历每个fd,调用fd的poll函数来检测fd的可用流,从所有的文件描述符中查找已就绪的文件描述符,并返回给用户就绪的数量
  • 用户通过遍历所有的fd,判断fd是否就绪,就绪在进行读取或写入操作
int select(int nfds,fd_set *readfds,fd_set *writefds,fd_set *exceptfds,struct timeval *timeout);//第一个参数是最大的文件描述符的值+1
void FD_CLR(int fd,fd_set *set); //将参数文件描述符fd对应的标志位设置为0
int FD_ISSET(int fd,fd_set *set); //判断fd对应的标志位是0还是1,返回值:fd对应的标志位的值如果是0则返回0,如果是1则返回1
void FD_SET(int fd,fd_set *set); //将参数文件描述符fd对应的标志位置为1
void FD_ZERO(fd_set *set);//fd_set 一共有1024bit,全部初始化为0

poll

POLL和SELECT的最大区别就是处理文件句柄的上限,SELECT 有文件句柄上线设置,值为FD_SETSIZE,而poll 理论上没有限制!

int poll(struct pollfd *fds, nfds_t nfds, int timeout);

epoll

epoll是linux特有的IO复用函数,epoll将用户关心的文件描述符上的时间来放到一个事件表中,无需像select和poll那样每次都传入文件描述符集或事件集。但是epoll需要一个额外的文件描述符来唯一标识内核中的这个事件表。这个描述符用epoll_create来创建。
Epoll 将这两个操作分开,先用 epoll_ctl 维护等待队列,再调用 epoll_wait 阻塞进程。显而易见地,效率就能得到提升。

  • 用户数据只需要拷贝一次
  • 通过回调函数实现
  • 直接将就绪的描述符返回给用户
#include 
// 创建epoll实例,通过一棵红黑树管理待检测集合
int epoll_create(int size);
// 管理红黑树上的文件描述符(添加、修改、删除)
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
// epfd : epoll实例对应的文件描述符
// op : 要进行什么操作: EPOLL_CTL_ADD: 添加; EPOLL_CTL_MOD: 修改; EPOLL_CTL_DEL: 删除;
//fd : 要检测的文件描述符
//event : 检测文件描述符什么事情
int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);// 检测epoll树中是否有就绪的文件描述符
//- epfd : epoll实例对应的文件描述符
//events : 传出参数,保存了发送了变化的文件描述符的信息
// maxevents : 第二个参数结构体数组的大小
//timeout : 阻塞时间 0 : 不阻塞;1 : 阻塞,直到检测到fd数据发生变化,解除阻塞; > 0 : 阻塞的时长(毫秒)

工作模式

你可能感兴趣的:(网络编程,网络)