• day38


    i/o模型

    '''
    默认情况下为阻塞I/O模型
    阻塞I/O:I/O指的就是输入输出,I/O会出现等待的问题,程序会一直

    存在问题:当执行的recv时,如果对象并没有发送数据,程序阻塞了,无法执行其他任务

    解决方案:
    多线程或者多进程,当客户端并发量非常大的时候,服务器可能就无法开启开启新的线程或者进程,如果不对数量 加以限制,服务器就崩溃了

    线程池或进程池

    协程:


    默认情况下就是阻塞IO模型:
    默认情况下就是阻塞IO模型
    当执行recv时,如果对方没有数据到达,那么程序阻塞在原地
    线程池, 有最大限制,不能无限的开线程
    协程

    非阻塞IO
    非阻塞 即 即使遇到了IO操作,也不会阻塞在原地,会继续往下执行
    server 是一个服务器socket对象
    server.setblocking(Fasle)设置为非阻塞
    每次读数据时,不一定有数据,为了能够及时处理数据,只能不停的询问,忙轮询

    多路复用




    异步IO

    '''
    ​网络IO中必经的两个阶段

    非阻塞I/O模型

    '''
    阻塞IO模型在执行recv和accept都会经历wait_data
    非阻塞IO即在执行recv和accep时,不会阻塞,可以继续往下执行


    如何使用:
    将severs.blocking(Flase)
    '''
    import socket
    import time

    server = socket.socket()
    server.setblocking(False)
    server.bind(('127.0.0.1',1688))
    server.listen()
    clients = []
    msgs = []

    try:
       client,addr = server.accept()
    clients.append(client)
    except BlockingIOError as e:
       print("还没有人链接过来")
       time.sleep()#
       for c in clients[:]:
               try: # 可能这个客户端还没有数据过来
                   # 开始通讯任务
                   data = c.recv(2048)
                   if not data:
                       c.close()
                       clients.remove(c)
                   #c.send(data.upper()) # 如果碰巧缓存区满了 这个数据就丢失了
                   # 由于此处捕获了异常 所以应该单独来处理发送数据
                   msgs.append((c,data))
               except BlockingIOError as e:
                   print("这个客户端还不需要处理.....",)
               except ConnectionResetError:
                   # 断开后删除这个客户端
                   c.close()
                   clients.remove(c)

           # 发送数据的操作
           for i in msgs[:]:
               try:
                   c,msg = i
                   c.send(msg.upper())
                   msgs.remove(i) # 如果发送成功! 删除这个数据  
               except BlockingIOError:
                   pass

    多路复用I/O模型

    '''
    多路指的是:多个socket对象 一个socket就是一个传输通道
    复用:意思是指使用同一个线程处理所有socket
    原理:
    在非阻塞IO模型中我们需要自己不断的询问操作系统是否有数据需要处理
    多路复用,使用select来监测是否有socket可以被使用
    '''
    import socket
    import select

    server = socket.socket()
    server.bind(('127.0.0.1', 1688))
    server.listen()

    # select最多检测1024个socket,超出直接报错,这是socket自身的问题,最终解决方案epoll
    rlist = [server]  # 将需要检测(是否可读recv)的socket对象放到该列表中
    # accept也是一个读数据的操作,默认也会阻塞,也需要select检测
    wlist = []  # 将需要检测(是否可写send)的socket对象放到该列表中

    msgs = []
    while True:
       r_list, w_list, _ = select.select(rlist, wlist, [])  # 会阻塞,等到有一个或者多个socket,可以被处理
       print(r_list, w_list)
       for soc in r_list:
           if soc == server:
               client, addr = server.accept()
               rlist.append(client)
           else:
               try:
                   data = soc.recv(2048)
                   if not data:
                       soc.close()
                       rlist.remove(soc)
                       continue
                   msgs.append((soc,data))
               except ConnectionResetError as e:
                   soc.close()
                   rlist.remove(soc)
                   print('这个客户端下线')
               # client.recv()
       for soc in w_list:
           for i in msgs[:]:
               if i[0] == soc:
                   soc.send(i[1])
                   msgs.remove(i)
           wlist.remove(soc)
  • 相关阅读:
    js append()和appendChild()和insertBefore()的区别
    webpack打包工具简单案例
    Vue $ref 的用法
    Vue学习笔记-作用域插槽
    Vue学习笔记-插槽基本使用
    Vue学习笔记-父子通信案例
    Echarts案例-折线图
    Echarts案例-柱状图
    软件构造实验三-递归下降分析分析法
    软件构造实验二-拷贝一个c文件 将其中的关键字int替换成float
  • 原文地址:https://www.cnblogs.com/zhuqihui/p/11000463.html
Copyright © 2020-2023  润新知