python select实现多IO监控
服务器
#使用socket模拟多线程,使多用户可以同时连接 import socket import select import queue sk1 = socket.socket() sk1.bind(('0.0.0.0', 8001)) sk1.listen() sk2 = socket.socket() sk2.bind(('0.0.0.0', 8002)) sk2.listen() inputs = [sk1, sk2] # 初始监控的对象列表中只有服务器端的socket对象 outputs = [] message_dict = {} while True: r_list, w_list, e_list = select.select(inputs, outputs, inputs, 1) # 第4个参数表示每1秒监控1次 print('正在监听的socket对象数%d' % len(inputs)) print(r_list) # 被监控的对象中,发生变化了的对象会被存入r_list列表中,开始运行时,因为没有任何对象发生变化,则为空列表 for sk1_or_conn in r_list: # 遍历发生了变化的对象 #每一个连接对象 if sk1_or_conn in [sk1, sk2]: # 如果发生了变化的对象sk1_or_conn是服务器的socket,表示有新的客户端请求接入 conn, address = sk1_or_conn.accept() # 与客户端连接,并将客户端socket对象信息存入两个变量中 conn.setblocking(False) # 设置非阻塞型 inputs.append(conn) # 将客户端连接对象加入监控列表中,以监控它是否有变化(即监控是否有消息发送过来) message_dict[conn] = queue.Queue() # 在消息字典中,建立以客户端为键名的键值对,值初始化为空列队 else: # 如果发生变化的对象sk1_or_conn不是服务器的socket,则表示此时的sk1_or_conn是客户端连接对象 ,即有客户端有消息发送过来了,也或者是客户端断开连接了。 try: data_bytes = sk1_or_conn.recv(1024) # 有消息则接收客户端消息 except Exception as ex: # 报异常时,表示客户端非正常的终止连接(强行退出) inputs.remove(sk1_or_conn) # 如果客户端断开了连接,则将客户端连接从监控列表中移除 message_dict.pop(sk1_or_conn) else: # 没报异常,则将接收到的消息转化为字符,并更新消息字典对应键名的值列表 if not data_bytes: # 客户端正常退出连接时 inputs.remove(sk1_or_conn) message_dict.pop(sk1_or_conn) else: data_str = str(data_bytes, encoding='utf-8') # 此为字符转化 if sk1_or_conn.getsockname() == ('127.0.0.1', 8001): # 判断客户端连接的是哪个服务器地址,以实现不同的响应 data = f'来自sk1:{data_str}' message_dict[sk1_or_conn].put(data) # 此为字典键值的值列队更新 else: message_dict[sk1_or_conn].put(f'来自sk2:{data_str}') outputs.append(sk1_or_conn) # 消息接收完后,将客户端连接对象存入准备写消息的监控列表中outputs #w_list中仅仅保存了谁给我发过消息 for conn in w_list: # 遍历写消息的监控列表 recv_str = message_dict[conn].get_nowait() # 从字典的值列队中取得准备回显的消息 conn.sendall(bytes(recv_str, encoding='utf-8')) # 将消息回复给客户端 outputs.remove(conn) # 回复完后就从监控列表中移除,以便准备给下一个回复消息 for sk in e_list: # 如果有监控列表中有发生异常变化的,该对象会被加入e_list列表中,对它进行遍历 inputs.remove(sk) # 发生异常即将其从监控列表中移除
客户端1
import socket obj = socket.socket() obj.connect(('127.0.0.1', 8001)) while True: inp = input('>>>') if inp == "": obj.close() break obj.sendall(bytes(inp, encoding='utf-8')) ret = str(obj.recv(1024),encoding='utf-8') print(ret)
客户端2
import socket obj = socket.socket() obj.connect(('127.0.0.1', 8002)) while True: inp = input('>>>') if inp == "": obj.close() break obj.sendall(bytes(inp, encoding='utf-8')) ret = str(obj.recv(1024),encoding='utf-8') print(ret)
浙公网安备 33010602011771号