各类IO模型
多路复用IO模型
server 端
from socket import *
import select
import time
s = socket()
s.bind(('127.0.0.1',8001))
s.listen()
data_dict= {}
r_list=[s]
w_list=[]
while 1:
readables,writables,_= select.select(r_list,w_list,[])
for i in readables:
print(i)
if i == s:
c,addr = i.accept()
r_list.append(c)
else:
try:
data = i.recv(1024)
if not data:
i.close()
r_list.remove(i)
continue
w_list.append(i)
data_dict[i]=data
except:
print('强行下线')
i.close()
r_list.remove(i)
for i in writables:
try:
i.send(data_dict[i].upper())
except:
i.close()
finally:
data_dict.pop(i)
w_list.remove(i)
client 端
import socket
c = socket.socket()
c.connect(("127.0.0.1", 9999))
print("connect....")
while True:
msg = input(">>>:").strip()
if not msg:continue
c.send(msg.encode("utf-8"))
data = c.recv(1024)
print(data.decode("utf-8"))
**
阻塞IO模型
**
server端
import socket
from threading import Thread
s = socket.socket()
s.bind(("127.0.0.1",9999))
s.listen()
def talking(c):
while True:
try:
data = c.recv(1024)
print("recv.....")
if not data:
c.close()
break
# send是一个本地io操作 速度非常快
c.send(data.upper())
except ConnectionResetError:
c.close()
break
while True:
c,addr = s.accept()
print("accept.....")
t = Thread(target=talking,args=(c,))
t.start()
client端
import socket
import os
c = socket.socket()
c.connect(("127.0.0.1", 9999))
print("connect....")
while True:
msg = "%s 发来问候 hello" % os.getpid()
if not msg:continue
c.send(msg.encode("utf-8"))
data = c.recv(1024)
print(data.decode("utf-8"))
非阻塞IO模型
server端
"""
非阻塞IO 即遇到IO操作也不导致程序阻塞,会继续执行
意味着即使遇到IO操作CPU执行权也不会被剥夺
程序效率就变高了
以下程序 占用CPU太高
原因是 需要无限的循环 去向操作系统拿数据
"""
import socket
import time
s = socket.socket()
s.bind(("127.0.0.1",9999))
s.listen()
# 设置socket 是否阻塞 默认为True
s.setblocking(False)
# 所有的客户端socket
cs = []
# 所有需要返回数据的客户端
send_cs = []
while True:
# time.sleep(0.2)
try:
c,addr = s.accept() # 三次握手
print("run accept")
cs.append(c) #存储已经连接成功的客户端
except BlockingIOError:
# 没有数据准备 可以作别的事情
# print("收数据")
for c in cs[:]:
try:
data = c.recv(1024)
if not data:
c.close()
cs.remove(c)
print(data.decode("utf-8"))
# 把数据和连接放进去
send_cs.append((c, data))
#c.send(data.upper()) # io
# send也是io操作 在一些极端情况下 例如系统缓存满了 放不进去 那肯定抛出
# 非阻塞异常 这时候必须把发送数据 单独拿出来处理 因为recv和send都有可能抛出相同异常
# 就无法判断如何处理
except BlockingIOError:
continue
except ConnectionResetError:
c.close()
# 从所有客户端列表中删除这个连接
cs.remove(c)
# print("发数据")
for item in send_cs[:]:
c,data = item
try:
c.send(data.upper())
# 如果发送成功就把数据从列表中删除
send_cs.remove(item)
except BlockingIOError: # 如果缓冲区慢了 那就下次再发
continue
except ConnectionResetError:
c.close() # 关闭连接
send_cs.remove(item) # 删除数据
# 从所有客户端中删除这个已经断开的连接
cs.remove(c)
client 端
import socket
c = socket.socket()
c.connect(("127.0.0.1", 9999))
print("connect....")
while True:
msg = input(">>>:").strip()
if not msg:continue
c.send(msg.encode("utf-8"))
data = c.recv(1024)
print(data.decode("utf-8"))