"""
----多路复用----
指的是
多个连接在复用一个线程
反过来说 一个线程处理多个连接
提高了单线程处理能
多路复用提升的 单线程处理网络IO的效率
协程提升的是 单线程处理所有IO的效率
"""
# 多路复用
import socket
import select
server = socket.socket()
server.bind(("127.0.0.1",21211))
server.listen()
# 将服务端设置为非阻塞
# server.setblocking(False)
# select 是帮我们监控连接
# 需要给它传两个列表 一个是检测是否可读(是否可以执行recv) 一个是检测是否可写(是否可执行send)
rlist = [server,]
wlist = []
# 默认select是阻塞的 会直到有其中一个或几个需要被处理
# 存储要发送的数据
msg = {}
# 返回值
# 1.可读的连接(可以执行recv)
# 2.可写的连接(可以执行send)
while True:
readable_list,writeable_list,_ = select.select(rlist,wlist,[])
# 接下来就是要处理这些可读可写列表
print(readable_list)
# 处理可读列表
for c in readable_list:
if c == server: # 说明当需要被处理的是服务器
client,addr = c.accept()
# 把客户端也交给select来检测
rlist.append(client)
else:
print("客户端可以recv啦!")
data = c.recv(1024)
print(data.decode("utf-8"))
# 给客户端返回数据
# c.send(data.upper())
wlist.append(c) # 将客户端也交给select检测是否可写
msg[c] = data
print(writeable_list)
print(msg)
# 处理可写列表
for w in writeable_list:
w.send(msg[w].upper())
# 将已经发送完成的连接从 检测列表删除
wlist.remove(w)
# ----多路复用实现原理----
# ----多路复用实现原理----
import socket
server = socket.socket()
server.bind(("127.0.0.1",21211))
server.listen()
server.setblocking(False)
# all clients
clients = []
while True:
try:
client,addr = server.accept()
clients.append(client)
except BlockingIOError:
# 存储所有已经关闭的客户端
close_ls = []
# 存储所有需要发送数据的客户端和数据
msg_ls = []
for c in clients:
try:
data = c.recv(1024)
if not data:
c.close()
close_ls.append(c)
# 把要发送数据的 客户端 和数据存储到列表中 单独发送
msg_ls.append((c,data))
except BlockingIOError:
pass
except ConnectionResetError:
c.close()
close_ls.append(c)
# 处理发送数据
# 已经发送完成的客户端和数据
sended_msg = []
for client_and_data in msg_ls:
c = client_and_data[0]
data= client_and_data[1]
try:
c.send(data.upper())
# 加入待删除列表
sended_msg.append(client_and_data)
except BlockingIOError:
pass
# 将已经发送成功的数据从待发送列表中删除
for i in sended_msg:
msg_ls.remove(i)
sended_msg.clear()
# 把已经关闭的连接从 所有客户端列表中删除
for i in close_ls:
clients.remove(i)
close_ls.clear()