day38

i/o模型

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

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

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

线程池或进程池

协程:


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

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

多路复用




异步IO

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

非阻塞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)
上一篇:log4cplus库的properties文件配置


下一篇:转载-Python学习笔记之文件读写