码迷,mamicode.com
首页 > 其他好文 > 详细

多路复用 阻塞/非阻塞IO模型 网络IO两个阶段

时间:2018-11-14 21:00:07      阅读:222      评论:0      收藏:0      [点我收藏+]

标签:handle   blocking   效率   nec   exec   data   def   []   not   

1.网络IO的两个阶段 waitdata copydata
send 先经历:copydata阶段
recv 先经历:waitdata阶段 再经历 copydata阶段


2.阻塞的IO模型
之前写的都是阻塞 无论多线程 多进程 还是进程池 线程池


3.非阻塞IO模型
非阻塞:最直接的体现 所有和读写相关的函数 都不会阻塞
意味着 在读写的时候 并不能确定目前是否可以读写 一旦不能读写就派出异常
只能使用try except 看是否可以读写
在非阻塞io中 需要不断循环询问操作是否需要处理的数据
这样一来 对应程序而言 效率确实高了
但是操作系统而言 你的程序就像一个病毒 一直强行占用cpu
当你的TCP程序 没有连接 没有数据接受 没有数据发送时 就是在做无用循环 浪费系统资源



4.多路复用 待改:有中间select recv等待结果
核心函数select
帮你检测所有的连接 找出可以被处理(可以读写)的连接
作为处理数据的一方 不再需要重复去向系统询问 select给你谁,你就用谁来处理


举例待改

举例1:迭代期间不能修改被迭代的对象
# li = [1,2,3,4,5,6]
# def mytlist_iter():
# for i in range(len(li)):
# yield li[i]
# for j in mytlist_iter():
# if j == 5:
# li.remove(5)
# d = {"a":1,"b":2}
# for k in d:
# if k == "a":
# d.pop(k)

举例2:(多路复用)
服务端:
from concurrent.futures import ThreadPoolExecutor
import socket

server = socket.socket()
# 重用端口
server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)

server.bind(("192.168.11.210",9999))

server.listen(5)

# 设置是否为阻塞 默认阻塞
server.setblocking(False)

def data_handler(conn):
print("一个新连接..")
while True:
data = conn.recv(1024)
conn.send(data.upper())
# 已连接的客户端
clients = []
# 需要发送的数据
send_datas = []
# 已经发送完的 需要删除的数据
del_datas = []
# 待关闭的客户端
closed_cs = []
while True:
try:
conn,addr = server.accept()
# 切到处理数据的任务去执行
# 代码走到这里才算是连接成功
# 把连接成功的客户端存起来
clients.append(conn)
except BlockingIOError:
# print("没有可以处理的连接 就干别的活儿")
#要处理的是已经连接成功的客户端
# 接收数据
for c in clients:
try:
data = c.recv(1024)
if not data:
# 对方关闭了连接
c.close()
# 从客户端列表中删除它
closed_cs.append(c)
continue
print("收到%s" % data.decode("utf-8"))
# 现在非阻塞 send直接往缓存赛 如果缓存满了 肯定有错误 需要单独处理发送
# c.send(data.upper())
send_datas.append((c,data))
except BlockingIOError:
pass
except ConnectionResetError:
# 对方关闭了连接
c.close()
# 从客户端列表中删除它
closed_cs.append(c)
# 处理发送数据
for data in send_datas:
try:
data[0].send(data[1].upper())
# 发送成功需要删除 不能直接删除
# send_datas.remove(data)
del_datas.append(data)
except BlockingIOError:
continue
except ConnectionResetError:
# 客户端连接需要删除
data[0].close()
closed_cs.append(data[0])
# 等待发送的数据需要删除
del_datas.append(data)
# 删除无用的数据
for d in del_datas:
#从待发送的列表中删除
send_datas.remove(d)
del_datas.clear()
for c in closed_cs:
clients.remove(c)
closed_cs.clear()

客户端:
import socket

c = socket.socket()

c.connect(("127.0.0.1",9999))

while True:
msg = input(">>>:")
if not msg:continue
c.send(msg.encode("utf-8"))
data = c.recv(1024)
print(data.decode("utf-8"))

多路复用 阻塞/非阻塞IO模型 网络IO两个阶段

标签:handle   blocking   效率   nec   exec   data   def   []   not   

原文地址:https://www.cnblogs.com/yanhui1995/p/9960038.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!