IO多路复用

  1. 非阻塞IO - TCP
    # =====================================  server
    import
    socket sock = socket.socket() sock.setblocking(False) sock.bind(('127.0.0.1',8888)) sock.listen(10) l_conn = [] while True: try: conn,addr = sock.accept() l_conn.append(conn) except BlockingIOError: err_con = [] for conn in l_conn: try: msg = conn.recv(1024) if msg == b'': err_con.append(conn) else: try: conn.send(msg.decode('utf-8').upper().encode('utf-8')) except BlockingIOError: pass finally: print(msg) except BlockingIOError: pass except ConnectionResetError: err_con.append(conn) for con in err_con: l_conn.remove(con) con.close() err_con.clear()
    # =================================================== client
    import
    socket import time sock = socket.socket() sock.connect(('127.0.0.1',8888)) for i in range(100): sock.send('hellow wlord'.encode('utf-8')) print(sock.recv(1024)) time.sleep(1)
  2. IO多路复用 - TCP (select)
    # =========================server
    import
    select import socket # select 和 poll 和epoll的区别 # # select和poll有一个共同的机制,都是采用轮训的方式去询问内核,有没有数据准备好了 # select有一个最大监听事件的限制,32位机限制1024,,6位机限制2048 # poll没有,理论上poll可以开启无限大,1G内存大概够你开10W个事件去监听 # # epoll是最好的,采用的是回调机制,解决了select和poll共同存在的问题 # 而且epoll理论上也可以开启无限多个监听事件 sock = socket.socket() sock.bind(('127.0.0.1',8888)) sock.listen(5) r_lst = [sock] w_lst = [] msg_dict = {} while r_lst: # 监听socket请求 r,w,x = select.select(r_lst,w_lst,r_lst)# 第一个参数是我们需要监听可读的套接字, 第二个参数是我们需要监听可写的套接字, 第三个参数使我们需要监听异常的套接字, 第四个则是时间限制设置. for i in r: # 判断是否有可读的请求 if i == sock: # 如果sock可读,说明有新的客户端前来链接 conn,addr = i.accept() # 链接新的客户端 r_lst.append(conn) # 将客户端的链接也放入可读套接字列表中继续监听 msg_dict[conn] = [] # 给每一个客户端都创建一个消息字典,回复消息的时候使用 else: # 如果不是sock那么,说明客户端有消息发过来 try: msg = i.recv(1024) # 接收消息 w_lst.append(i) # 将连接加入可写监听 except ConnectionResetError: # 如果客户端意外断开连接,会爆这个错误 msg = b'' if msg == b'': # 如果客户端发过来的是空消息,那么代表客户端已经断开连接 r_lst.remove(i) # 在可读套接字列表中删除当前连接 i.close() # 关闭连接 del msg_dict[i] # 删除保存的消息记录 else: print(msg) msg_dict[i].append(msg.decode('utf-8').upper().encode('utf-8'))# 将客户端传过来的消息转换成大写,保存起来。当做回复消息 for i in w: # 判断是否有可写消息 msg = msg_dict.get(i) # 判断消息字典中是否存在 当前链接,如果不存在说明当前客户端已经关闭 if msg: # 如果存在则返回消息 i.send(msg.pop()) w_lst.remove(i) else: # 如果不存在,则在监听列表中删除当前链接 if i in r_lst: r_lst.remove(i) for i in x: # 判断是否有出错的接连,如果有直接删除,并且关闭连接 if i in r_lst: r_lst.remove(i) if i in msg_dict: del msg_dict[i] i.close()
    # ====================== client
    import
    socket sock = socket.socket() sock.connect(('127.0.0.1',8888)) while True: msg = input('>>>') if msg == '': continue if msg == 'q': break sock.send(msg.encode('utf-8')) print(sock.recv(1024)) sock.close()
原文地址:https://www.cnblogs.com/wtil/p/11238311.html