典型IO模型(中)

多路转接IO:

  • 多路转接IO,牛逼的地方在于可以监控多个文件描述符,判断多个描述符是否准备就绪。
  • 多路转接lO模型: select, poll, epoll ==》 高并发的基础。

select:

  • 原理
    • 多路转接本质上就是将多个文件描述符放到内核当中,让内核进行监控,内核在监控多个文件描述符的时候, 一旦发现有文件描述符所对应的事件就绪,则返回该文件描述符, 让用户执行流进行相应事件的处理。

  • 接口
    • nfds : 内核遍历事件集合的范围,取决于我们传递给内核最大文件描述符
      nfds = 最大文件描述符的数值 + 1。
    • readfds : 读事件集合
    • writefds : 写事件集合
    • exceptfds: 异常事件集合
    • timeout :
      • NULL : 则表示阻塞监控,select帮调用者监控的文件描述符如果没有事件就绪的,则select一直阻塞。
      • 0 : (tv_ sec=0 && tv_ usec=0) : 表示非阻塞监控,在调用者调用select的时候, select会轮询遍历一次,如果没有就绪的文件描述符,则直接返回。如果有就绪的文件描述符,就返回就绪的文件描述符。 我们需要搭配循环使用。
      • 带有超时时间的监控 (tv_ sec> 0 || tv_ usec> 0), 在调用者调用select的时候,select会轮询遍历事件集合, 在轮询遍历的过程当中,如果监控的文件描述符一 直没有对应的事件产生,知道超过超时时间,则select返回。 如果在超时时间内,监控的文件描述符产生了对应的事件,则无需等待超时时间,直接返回。

 一个文件描述符有可能会产生三类事件,读,写,异常,用户如果关心文件描述符的某一类事件,则将该文件描述符添加到对应的事件集合当中。

  • 注意: 不用去纠结数组到底有多少元素个数,因为我们在使用的时候,并不是按照数组元素的方式来使用的, 而是按照比特位的方式来使用的。

         言外之意,就是事件集合本质上是一个位图。

  • 宏 “_ FD SETSIZE" 本质上在内核当中已经写死为1024了,也就是意味着事件集合最多可以使用1024个比特位,每一 个比特位对应1个文件描述符,那也就是意味着,select最多监控1024个文件描述符。

  •  void FD _CLR(int fd, fd_ set *set)
    • 将fd文件描述符从事件集合当中移除,本质上就是将文件描述符所对应的比特位置为0。
  • int FD_ ISSET(int fd, fd_ set *set)
    • 判断fd文件描述符是否在事件集合set当中,本质上就是在判断文件描述符fd所对应的比特位是否为1。
      • 如果当前比特位为0,则表示不在, FD_ ISSET函数返回0。
      • 如果当前比特位为1,则表示在,fd_ ISSET函数返回1。
  • void FD_ SET(int fd, fd_ set *set)
    • 将文件描述符fd,添加到事件集合set当中,本质上就是将文件描述符对应的比特位设置成为1。
  • void FD_ZERO(fd_ set *set)
    • 清空事件集合,将所有比特位全部设置成为0。
  • 使用select改造单线程的tcp代码
    • 单线程tcp代码存在的问题:
      • accept函数一旦调用,当没有新的来连接到来的时候, 会阻塞recv函数阻塞调用,当没有新的数据到来的时候,会阻塞。
      • 第一种情况: 要么将accept函数和recv函数放到while循环的内部, 则我们能够接收很多客户端, 但是每一个客户端只能聊一个来回。
      • 第二种情况: 要么将accept函数放到while循环的外面,则服务端只能接收一个客户端, 但是可以和这个客户端聊很多。
  • 使用select解决该问题的一个原理:
    • 使用select监控listen_ sockfd和new_ sockfd,一旦select发现某个文件描述符就绪,则返回,我们的程序进行判断:
      • 如果说: 返回的是listen_ sockfd,则accpet接收新连接。
      • 如果说: 返回的是new_ sockfd,则recv接收新连接。
    • 因为 select 已经监控到了文件描述符的事件,所以,直接调用的时候,一定不会陷入阻塞。

select的优缺点:

  • 优点:
    • According to POSIX.1-2001 */,遵循posix标准, 可以跨平台使用,可以在win平台使用,也可以在linux平台使用。
    • select的超时时间可以精确到微妙。
  • 缺点:
    • select监控文件描述符的时候,采用轮询遍历的方式, 随着监控的文件描述符越多,监控(轮询)效率越低。
    • select监控文件描述符的个数是由上限的,上限取决于内核当中的宏_ FD_ SETSIZE, 这个宏的值为1024。
    • select在返回就绪文件描述符的时候,会将未就绪的文件描述符从事件集合当中移除掉, 导致二次监控的时候,程序员需要再次手动添加。
    • 在返回就绪文件描述符的时候,是返回了一个事件集合,并不是将就绪的文件描述符数值直接返回给调用者, 需要调用者使用FD_ ISSET函数进行判断哪些文件描述符就绪了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值