设为首页 收藏本站
查看: 1006|回复: 0

[经验分享] python_day11_IO模型

[复制链接]

尚未签到

发表于 2018-8-11 06:45:31 | 显示全部楼层 |阅读模式
  事件驱动编程思想
  范式: 一种写代码的方式 ,这里程序的执行是由外部事件来决定的。它的特点是包含一个事件循环,当外部事件发生时使用回调机制来触发相应的处理。
  触发事件发送到队列,然后提取事件任务,发送到执行任务函数
  当CPU指令集为 0的时候对应的是内核态(拥有硬件,软件所有权限), 1为用户态
  用户态: 用户所运行的程序,
  内核态: 操作系统
  进程阻塞:正在执行的进程,由于期待的事件未发生,如请求系统资源失败,等待某种操作的完成,则由系统自动执行阻塞,使进程进入阻塞状态, 进程阻塞是不占用CPU资源的
  缓存I/O : 标准IO操作数据流向路径:数据——流缓存区——内核缓存区——磁盘
  数据--> 用户态 --> 内核态 --> 对端 内核态 --> 用户态 --> 对应应用程序 --> 数据
  IO模型
  阻塞
  非阻塞
  IO多路复用
  异步IO
  1、阻塞IO   全程阻塞  缺点:CPU不能做其它事情  优点: 数据同步
  例: 比如以socket为例,当服务启动之后,accept发起一个系统调用,由用户态到内核态,操作系统(内核态)一直等待数据(程序阻塞),当启动client端连接到s端,内核态接收到数据,数据从内核态复制到用户态,最后返回给conn
  缺点: 阻塞跟同步类似,都是你发我收, 我发你收 ,CPU将会一直阻塞,
  #####  阻塞IO
  '''IO 每次连接都只能连接一次,如果有其它客户端需要连接就需要等待本次连接断开'''
# server.py  
import socket
  

  
so=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
  
ipport=('127.0.0.1',9001)
  
so.bind(ipport)
  
so.listen(5)
  

  
while True:
  
    conn,data=so.accept()
  
    print(conn)
  2、非阻塞IO
  setblocking(False)
  例: 服务端发起系统调用,查看内核态是否有数据,如果有就直接返回,如果也直接返回但会隔一段时间就会重新再去内核态在查看。
  缺点: 系统调用发送太多,占据大量的数据资源, 当数据在前1秒发送时,而服务端正在阻塞就会导致数据无法及时处理
  #####  非阻塞IO
  ''' setblocking socket等待用户进行连接,如果没有客户端进行连接,将会每隔一段时间查询一次内核态里是否有数据 '''
import socket  
import time
  

  
so=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
  
ipport=('127.0.0.1',9001)
  
so.bind(ipport)
  
so.listen(5)
  
so.setblocking(False)
  

  
while True:
  
    try:
  
        conn,data=so.accept()
  
        print(conn)
  
    except Exception as F:
  
        print(F)
  
        time.sleep(5)
  # 同阻塞client.py
  3、IO多路调用
  select.select([bindname,],[],[],5)
  input output errorput 每隔几秒钟监听
  select发起系统调用,内核态当发现有数据时返回给select,然后server端再发送一次recvfrom
#####  IO多路复用 server端  
import socket
  
import selectors
  
import json
  
ipport=('127.0.0.1',9001)
  

  
sel=selectors.DefaultSelector()
  

  
sock=socket.socket()
  
sock.bind(ipport)
  
sock.listen(5)
  

  
class UpDown:
  
    def put(self,obj,**data):
  
        print('ok')
  
        print(data)
  
        obj.send('ok'.encode('utf-8'))
  

  
def accept(obj,mask):
  
    # 与客户端建立连接 就跟socket 配置的 socket.accept是一个意思,只不过这里配置的是异步io可以同步连接多个客户端
  
    conn,addr=obj.accept()
  
    # print('client informaster: ',conn,'client addr: ',addr)
  
    # 注册客户端conn文件描述符对象,并绑定read函数
  
    sel.register(conn,selectors.EVENT_READ,read)
  

  
def read(obj,mask):
  
    try:
  
        data = obj.recv(1024)
  
        obj.send(data)
  
    except Exception as E:
  
        sel.unregister(obj)
  
        obj.close()
  

  
sel.register(sock,selectors.EVENT_READ,accept)
  

  
while 1:
  
    # 监听
  
    events=sel.select()
  
    # 如果没有客户端连接就是为空
  
    # 客户端第一次连接获取的是sock对象,绑定accept函数并执行,
  
    # 客户端发送数据 绑定read函数再进行数据的接收或发送操作
  
    for key,mask in events:
  
        print(key.data)
  
        # 获取socket文件描述符,并获取register注册函数accept  (sel.register(sock, selectors.EVENT_READ,accept))
  
        conn=key.data
  
        # key.fileobj方法 获取的是客户端的socket文件描述符对象 <socket.socket fd=268, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9001)>
  
        # mask不知道有啥用 可以不配置它
  
        conn(key.fileobj,mask)
  # 客户端   (只实现了简单的发送接收,错误处理没弄)
import socket  
so=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
  
ipport=('127.0.0.1',9001)
  
so.connect(ipport)
  
while True:
  
    inp=input('>>>>>: ')
  
    so.send(inp.encode('utf-8'))
  
    data=so.recv(1024)
  
    print(data.decode('utf-8'))
  触发方式: 两种
  1、 水平触发
  只有高电平(1)或低电平(0)时才触发通知,只要在这两种状态就能得到通知,上面提到的只要有数据可读(描述符就绪)那么水平触发的epooll就立即返回
  2、 边缘触发
  只有电平发生变化(高电平到低电平,或电低平到高电平)的时候才触发通知,
  3、IO多路复用优势:同时可以监听多个连接
  IO多路复用: 单线程下实现的并发, 原理:利用IO空闲时间
  select: 效率最慢   windows下只有这个, linux三个都有,最大量只有1024个连接
  poll:
  epoll: 效率最快,
  只要有一点点阻塞就是同步IO
  4、异步IO
  异步最大特点: 全程无阻塞,但系统内核运行会很忙碌
  用户进程 发起调用,没有数据立刻返回,进程继续执行, 内核会一直等待数据,当内核收到数据,会将数据复制到用户态并直接返回给进程
  阻塞与非阻塞区别
  阻塞,全程阻塞
  非阻塞,只在数据从内核态到用户态那一段时间内阻塞
  同步IO与异步IO
  同步IO: 只要有阻塞的就是同步IO
  异步IO: 不带一丝阻塞的就是异步IO

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-549808-1-1.html 上篇帖子: [python] linux下安装paramiko模块记录 下篇帖子: python面向对象——类属性和实例属性
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表