• 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()
  • 相关阅读:
    C++我们必须要熟悉的事之具体做法(3)——类的设计与声明
    C++我们必须要了解的事之具体做法(1)——构造、复制构造、析构、赋值操作符背后的故事
    STL hash table, Unordered Contains
    多个生产者——多个消费者模型(互斥量条件变量实现)
    将UNIX网络编程卷2的库函数合并到卷1的库函数中
    进程间通信(三)——Posix共享内存区
    进程间同步(1)——条件变量和互斥量
    进程间通信(二)——Posix消息队列
    python使用百度翻译api
    screen命令
  • 原文地址:https://www.cnblogs.com/wtil/p/11238311.html
Copyright © 2020-2023  润新知