【无标题】

在这里插入图片描述

服务器要接受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.主动轮询效率很低

poll:

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

epoll:

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

总结
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 多长时间轮训-降低

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,不然最后会被阻塞。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值