• 【无标题】


    在这里插入图片描述

    服务器要接受a、b、c、d、e几个客户端的数据;客户端越多,服务器维持的连接也要越多。随着n多个客户端的,如何知道客户端发送到服务器端的数据?调用receive函数之前,如何知道有数据来的?把所有的io所有的socket放在一起,中间有数据来了,立马可以检测得到叫做io多路复用,select、poll、epoll。
    作用:io放在一起,加在epoll这种io多路复用里面检测到什么数据可以读,这时候就可以调用receive。

    • 关于 epoll 和 select 的区别
      链接
      select 基于轮训机制
      epoll基于操作系统支持的I/O通知机制 epoll支持水平触发和边沿触发两种模式。
      select缺点:
    单个进程可监视的fd数量被限制(321024,642048)
    对socket是线性扫描,即轮询,效率较低:浪费cpu时间
    内核需要将消息传递到用户空间,都需要内核拷贝动作。需要维护一个用来存放大量fd的数据结构,使得用户空间和内核空间在传递该结构时复制开销大。
    1.每次调用select,都需把fd集合从用户态拷贝到内核态,fd很多时开销就很大
    2.同时每次调用select都需在内核遍历传递进来的所有fd,fd很多时开销就很大
    3.select支持的文件描述符fd数量太小了,默认最大支持10244.主动轮询效率很低
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    poll:

    poll没有最大文件描述符数量的限制。其余也与select相似,基于轮训
    
    • 1

    epoll:

    1.事件驱动,修改主动轮询为被动通知
    2.LT,默认的模式(水平触发) 只要该fd还有数据可读,每次 epoll_wait 都会返回它的事件,提醒用户程序去操作,
    ET是“高速”模式(边缘触发)
    没有最大连接数限制、效率提升、内存拷贝、epoll内核空间和用户空间共享内存
    
    • 1
    • 2
    • 3
    • 4

    总结
    4 总结
    select,poll,epoll都是IO多路复用机制,即可以监视多个描述符,一旦某个描述符就绪(读或写就绪),能够通知程序进行相应读写操作。 但select,poll,epoll本质上都是同步I/O,因为他们都需要在读写事件就绪后自己负责进行读写,也就是说这个读写过程是阻塞的,而异步I/O则无需自己负责进行读写,异步I/O的实现会负责把数据从内核拷贝到用户空间。
    select,poll实现需要自己不断轮询所有fd集合,直到设备就绪,期间可能要睡眠和唤醒多次交替。而epoll其实也需要调用epoll_wait不断轮询就绪链表,期间也可能多次睡眠和唤醒交替,但是它是设备就绪时,调用回调函数,把就绪fd放入就绪链表中,并唤醒在epoll_wait中进入睡眠的进程。虽然都要睡眠和交替,但是select和poll在“醒着”的时候要遍历整个fd集合,而epoll在“醒着”的时候只要判断一下就绪链表是否为空就行了,这节省了大量的CPU时间。这就是回调机制带来的性能提升。
    select,poll每次调用都要把fd集合从用户态往内核态拷贝一次,并且要把current往设备等待队列中挂一次,而epoll只要一次拷贝,而且把current往等待队列上挂也只挂一次(在epoll_wait的开始,注意这里的等待队列并不是设备等待队列,只是一个epoll内部定义的等待队列)。这也能节省不少的开销。

    • accept的listen的实现

    • udp并发的实现
      qq早期版本用udp?为什么用udp?
      tcp面向连接,服务器上面通过select只能用来检测fd,一个进程里面fd不能太多。1024个
      selsect要copy到内核,然后再copy出来。

    select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout);
    nfds 遍历循环
    timeout 多长时间轮训-降低
    
    • 1
    • 2
    • 3

    selsect中的fd不能太多,nfds穿的不是数量,而是传的最大值。
    tcp并发量不高,udp高吗?不是因为这样
    udp并发可以模拟tcp,可以采用不用管理fd可以采用一个连接
    早期只有select
    现在有了epoll可以用tcp,io数量增加。
    云主机默认选择linux,跟epoll关系很大;epoll检测是否有数据

    udp服务器分配fd,再发一个数据,这样可以避免每一个链接里面的脏数据。
    异步io,

    • 出现了大量的close-wait
      如何解决?看业务逻辑被动关闭方描述
      -出现了大量time-wait
      建立连接断开,timewait时间设置短一些,设置可重用

    为什么et模式下,socket文件描述符要设置成非阻塞的?
    阻塞IO:当你去读一个阻塞的文件描述符时,如果在该文件描述符上没有数据可读,那么它会一直阻塞(通俗一点就是一直卡在调用函数那里),直到有数据可读。当你去写一个阻塞的文件描述符时,如果在该文件描述符上没有空间(通常是缓冲区)可写,那么它会一直阻塞,直到有空间可写。以上的读和写我们统一指在某个文件描述符进行的操作,不单单指真正的读数据,写数据,还包括接收连接accept(),发起连接connect()等操作…

    非阻塞IO:当你去读写一个非阻塞的文件描述符时,不管可不可以读写,它都会立即返回,返回成功说明读写操作完成了,返回失败会设置相应errno状态码,根据这个errno可以进一步执行其他处理。它不会像阻塞IO那样,卡在那里不动!!!

    Level_triggered(水平触发):当被监控的文件描述符上有可读写事件发生时,epoll_wait()会通知处理程序去读写。如果这次没有把数据一次性全部读写完(如读写缓冲区太小),那么下次调用 epoll_wait()时,它还会通知你在上没读写完的文件描述符上继续读写,当然如果你一直不去读写,它会一直通知你!!!如果系统中有大量你不需要读写的就绪文件描述符,而它们每次都会返回,这样会大大降低处理程序检索自己关心的就绪文件描述符的效率!!!

    Edge_triggered(边缘触发):当被监控的文件描述符上有可读写事件发生时,epoll_wait()会通知处理程序去读写。如果这次没有把数据全部读写完(如读写缓冲区太小),那么下次调用epoll_wait()时,它不会通知你,也就是它只会通知你一次,直到该文件描述符上出现第二次可读写事件才会通知你!!!这种模式比水平触发效率高,系统不会充斥大量你不关心的就绪文件描述符!!!
    所以ET所以循环处理,保证能将数据读取完毕,即同时要保证非阻塞IO,不然最后会被阻塞。

  • 相关阅读:
    [UE]node.js 报错解决办法 throw er;// Unhandled ‘error‘event解决某个端口被占用的情况
    【单片机仿真】(一)Proteus8.9 安装教程
    vue3 路由新玩法useRoute 和useRouter
    8086寄存器和常用指令缩写还原
    有些段子,外行人根本看不懂,只有程序员看了会狂笑不止
    【Python机器学习】零基础掌握IsolationForest集成学习
    Nginx的安全控制
    项目完成小结 - Django3.x版本 - 开发部署小结 (2)
    厦门城市内涝的落地解决方案,城市内涝积水监测系统
    【Linux】shell命令运行原理---认识Linux基本指令
  • 原文地址:https://blog.csdn.net/weixin_45363995/article/details/126261083