其他分享
首页 > 其他分享> > day39

day39

作者:互联网

day39   traceback.print.exc() 捕获异常 join的注意点   IO模型     模型就是解决某个问题的套路 IO问题     输入输出     需要一个用吗来执行登陆操作,问题是用户名需要用户输入,输入需要耗时,如果输入没有完成,后续的逻辑无法继续,所以默认处理方式就是等待. 怎么等(将当前进程阻塞住,切换至其他进程执行,等到按下回车键,拿到用户名,再唤醒刚才的进程,将状态调整为就绪态),这个处理方案就称之为,阻塞IO模型         网络IO中必经的两个阶段 copy犹豫是本地IO,所以速度非常快,不是我们要解决的     ################ 存在的问题:     当执行到recv的时候,如果对方没有发送数据,程序阻塞,无法执行其他任务 解决方案:     多线程,多进程:             当客户端并发量非常大的时候,服务器资源就无法开启新的线程或者进程,如果不对数量加以限制,服务器就容易崩了,     线程池或者进程池             1.限制了数量,保证服务器正常运行,但是问题是如果客户端都处于阻塞状态,这些线程,就业阻塞了.     协程:             使用一个线程处理所有客户端,当一个客户端处于阻塞状态时,就可以切换到其他客户端任务     非阻塞IO模型       阻塞IO模型在执行recv和accept的时候,都需要经历一个wait data.         非阻塞IO模型在执行recv和accept的时候不阻塞,会往下执行     代码???? 非阻塞IO模型(还没全) 服务器 import socket server = socket.socket() server.bind(("127.0.0.1",1688)) server.listen() server.setblocking(False) clients = [] while True: try: client,addr = server.accept() clients.append(client) except BlockingIOError as e: # print(e) for c in clients[:]: try: data = c.recv(2048) c.send(data.upper()) except BlockingIOError as e: print("不需要处理") except ConnectionResetError as e: clients.remove(c) # print("==============",len(clients))     如何使用:         将server的blocking设置为False,非阻塞 存在的问题         这样一来,进程效率非常高,没有任何的阻塞         但是很多情况下,并没有很多数据需要处理,但是我们的进程也需要不停的问操作系统,所以会导致CPU占用过高.并且这个            是 无意义的 多路复用   多个socket对象,一个socket就是一个传输通道 复用:就是同一个线程处理所有socket. 原理,在非阻塞IO模型中,我们需要不断的询问操作系统,是否有数据需要处理,造成资源浪费.         多路复用,使用select,来检测是否与有socket,可以被处理     #########多路复用代码初级 select参数: 参数1:rlist,里面存储需要被检测是否可读的(是否可以执行recv)socket对象 参数2:wlist,里面存储需要被检测是否可写的(是否可以执行send)socket对象 参数3:xlist,就是存储需要关注的异常条件 参数4:timeout超时时间,超过一定时间,还是没有可以被处理的socket,就返回空列表 返回值   三个列表 1,已经有数据到达的socket对象 2.可以发送数据的socket对象.怎么叫可以发,就是缓冲区没满 3不管   import socket import select server = socket.socket() server.bind(("127.0.0.1",1888)) server.listen() rlist = [server,] wlist =[] while True:     readable_list,wirteable_list,_ = select.select(rlist,wlist,[])     print(readable_list,wirteable_list)     for soc in readable_list:         if soc == server:             client,addr = server.accept()             rlist.append(client)           else:             data = soc.recv(2048)             if not data:             soc.close()                rlist.remove(soc)                 continue             soc.send(data.upper())   ############多路复用代码终极     import socket import select server = socket.socket() server.bind(("127.0.0.1",1688)) server.listen()   # server.setblocking(False)   rlist = [server,]  # 将需要检测(是否可读==recv)的socket对象放到该列表中                    # accept也是一个读数据操作,默认也会阻塞  也需要让select来检测   # 注意 select最多能检测1024个socket 超出直接报错    这是select自身设计的问题    最终的解决方案epoll   wlist = []  # 将需要检测(是否可写==send)的socket对象放到该列表中             # 只要缓冲区不满都可以写   msgs = [("socket","msg")]  # 存储需要发送的数据  等待select 检测后 在进行发送     print("start") while True:     readable_list,writeable_list,_ = select.select(rlist,wlist,[])  # 会阻塞等到 有一个或多个socket 可以被处理     print("%s个socket可读" % len(readable_list),"%s个socket可写" % len(writeable_list))       """     readable_list 中存储的是已经可以读取数据的socket对象   可能是服务器 可能是客户端     """     # 处理可读列表     for soc in readable_list:         if soc == server:             # 服务器的处理             client,addr = server.accept()             #将新连接的socket对象 加入到待检测列表中             rlist.append(client)         else:             try:                 # 客户端的处理                 data = soc.recv(2048)                 if not data:                     soc.close()                     rlist.remove(soc)   # 如果对方下线  关闭socket 并且从待检测列表中删除                     continue                 # 不能直接发  因为此时缓冲区可能已经满了    导致send阻塞住, 所以要发送数据前一个先这个socket交给select来检查                 # soc.send(data.upper())                 if soc not in wlist:                     wlist.append(soc)                 # 将要发送的数据先存起来                 msgs.append((soc,data))             except ConnectionResetError:                 soc.close()                 # 对方下线后 应该从待检测列表中删除 socket                 rlist.remove(soc)                 wlist.remove(soc)     # 处理可写列表     for soc in writeable_list:         # 由于一个客户端可能有多个数据要发送 所以遍历所有客户端         for i in msgs[:]:             if i[0] == soc:                 soc.send(i[1])                 # 发送成功  将这个数据从列表中删除                 msgs.remove(i)         # 数据已经都发给客户端   这个socket还需不需要检测是否可写,必须要删除         wlist.remove(soc) # 否则 只要缓冲区不满 一直处于可写 导致死循环    

标签:soc,rlist,socket,day39,list,server,select
来源: https://www.cnblogs.com/yclzp/p/11000605.html