IO模型

模型就是解决某个问题的套路 

IO问题:

输入输出 

我要一个用户名用来执行登陆操作,问题用户名需要用户输入,输入需要耗时,  如果输入没有完成,后续逻辑无法继续,所以默认的处理方式就是 等

将当前进程阻塞住,切换至其他进程执行,等到按下回车键,拿到了一个用户名,再唤醒刚才的进程,将状态调整为就绪态

 

以上处理方案  就称之为阻塞IO模型

 

存在的问题:

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

解决方案:

多线程或多进程,

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

线程池或进程池

首先限制了数量 保证服务器正常运行,但是问题是,如果客户端都处于阻塞状态,这些线程也阻塞了

协程:

使用一个线程处理所有客户端,当一个客户端处于阻塞状态时可以切换至其他客户端任务  

 

非阻塞IO模型

阻塞IO模型在执行recv 和 accept  时 都需要经历wait_data 

非阻塞IO即 在执行recv 和accept时 不会阻塞 可以继续往下执行

 

如何使用:

将server的blocking设置为False 即设置非阻塞 

 

存在的问题 :

这样一来 你的进程 效率 非常高 没有任何的阻塞

很多情况下 并没有数据需要处理,但是我们的进程也需要不停的询问操作系统  会导致CPU占用过高

而且是无意义的占用 

案例:

import socket
import time

server = socket.socket()
server.bind(("192.168.13.103",1688))
server.listen()
server.setblocking(False) # 默认为阻塞   设置为False 表示非阻塞

# 用来存储客户端的列表
clients = []

# 链接客户端的循环
while True:
   try:
       client,addr = server.accept()   # 接受三次握手信息
       # print("来了一个客户端了.... %s" % addr[1])
       # 有人链接成功了
       clients.append(client)
   except BlockingIOError as e:
       # print("还没有人连过来.....")
       # time.sleep(0.5)
       # 服务你的客人去
       for c in clients[:]:
           try: # 可能这个客户端还没有数据过来
               # 开始通讯任务
               data = c.recv(2048)
               c.send(data.upper())
           except BlockingIOError as e:
               print("这个客户端还不需要处理.....",)

           except ConnectionResetError:
               # 断开后删除这个客户端
               clients.remove(c)
       print("=======================",len(clients))

 

多路复用IO模型

import socket

client = socket.socket()
client.connect(("127.0.0.1",8080))
while True:
msg = input("masg:")
if not msg:continue
client.send(msg.encode("utf-8"))
print(client.recv(2048).decode("utf-8"))
#服务器select模块
import socket

import select

server=socket.socket()

server.bind(("127.0.0.1",8080))

server.listen(5)

rlist=[server,]

wlist=[]

msg=[]

while True:
read_able_list, write_able_list, _ = select.select(rlist, wlist, [])
for soc in read_able_list:
if soc == server:
client, addr = server.accept()
rlist.append(client)
print(rlist)
else:
try:
data = soc.recv(1024)
if not data:
soc.close()
rlist.remove(soc)
continue
# soc.send(data)
wlist.append(soc)
msg.append((soc, data))
except Exception as e:
soc.close()
rlist.remove(soc)
if soc in wlist:wlist.remove(soc)
for soc in read_able_list:
for i in msg:
if i[0] == soc:
i[0].send(i[1])
msg.remove(i)
wlist.remove(soc)
posted on 2019-06-10 18:40  郝俊连城  阅读(95)  评论(0编辑  收藏  举报