C语言--day32

TCP并发服务器

  • 单循环服务器:一次只能处理一个客户端任务的服务器
  • 并发服务器:能够同时处理多个客户端任务的服务器

TCP并发服务端:

  • 多进程
  • 安全、资源开销大、并发量小
  • 多线程
  • 相对进程资源开销小,相对并发量大
  • 线程池
  • 提前创建好大量线程管理起来,避免反复创建线程带来时间消耗
  • 生产者--消费者 设计模式
  • IO多路复用
  • 文件 --->>fd
  • 对多个文件描述符的监测,复用一个进程。
  • select
  • poll
  • epoll

Linux常用IO模型

阻塞IO
  • fgets()

  • read()

  • fread()

  • recv()

  1. 让多个IO具有先后顺序
  2. 节省CPU资源
非阻塞IO
  1. 搭配轮询方式实现
  2. 浪费CPU资源
信号驱动IO
  1. 效率高

  2. 驱动的信号个数有限,应用层无法区分多个IO事件

IO多路复用
  • 在一个进程中,同时监测多个IO
  1. select
  2. poll
  3. epoll
  • 创建文件描述符集合
  • 添加需要监测的文件描述符到集合
  • 通知内核开始监测
  • 由IO事件到达时,监测返回结果
select:
复制代码
    int select(int nfds, fd_set *readfds, fd_set *writefds,
                  fd_set *exceptfds, struct timeval *timeout);
功能:通知内核监测文件描述符中的事件
参数:
               nfds :集合中最大的文件描述符+1
               readfds:读事件的文件描述符集合
               writefds:写事件的文件描述符集合
               exceptfds:其他
               timeout:超时时间
                      NULL :不设置超时时间(阻塞)

返回值:
    成功:返回到达事件的个数
    失败:-1
    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的特点:
  1. select使用数组(位图)保存文件描述符集合,最多允许监测1024个文件描述符
  2. select将集合表创建在应用层,需要应用层和内核层的反复数据拷贝
  3. select需要遍历寻找到达的IO事件,效率低
  4. select只能工作在水平触发模式(低速模式),不能工作在边沿触发模式(高速模式)
poll的特点:
  1. poll使用链表保存文件描述符集合,理论上没有文件描述符限制
  2. poll将集合表创建在应用层,需要应用层和内核层的反复数据拷贝
  3. poll需要遍历寻找到达的IO事件,效率低
  4. poll只能工作在水平触发模式(低速模式),不能工作在边沿触发模式(高速模式)
epoll的特点:
  • epoll使用树形结构保存文件描述符集合(红黑树)

  • epoll将结合表直接创建在内核层,避免应用层和内核层的反复数据拷贝

  • epoll直接返回到达的事件,不需要应用层遍历查找

  • epoll可以工作在水平触发模式(低速模式),也可以工作在边沿触发模式(高速模式)

    复制代码
      int epoll_create(int size);

    功能:创建文件描述符集合
    参数:
    size:监测的文件描述符的最大上限
    返回值:
    成功:返回集合代表的文件描述符
    失败:-1

    复制代码
      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 */
             };
             
      int epoll_wait(int epfd, struct epoll_event *events,
                        int maxevents, int timeout);

    功能:通知内核开始监测文件描述符集合并等待返回监测到的事件结果
    参数:
    epfd:文件描述符集合
    events:保存到达事件的数组
    maxevents:监测的事件最大个数
    timeout :超时时间
    -1 :不设置超时
    返回值:
    成功:返回到达事件的个数
    失败:-1