# 这里异步服务器的实现是借助于select,有关select模块在我上边的博客中有体现。# zen_utils也是咱们本身写的一个脚本。也在上边的磨课中import select, zen_utils,queue,timedef serve(listener,inpouts,outputs,message_queues): while inputs: print('等待开始第一个线程链接1111') # 开始select监听,对input_list中的服务器端的server开始进行监听 # 一旦调用socket的send,recv函数,将会再次调用此模块 # 这里监控三个参数,第一个返回的是可读的list, 第二个存储的是可写的list, 第三个存储的是错误信息的 readable, writeable, errorinfo = select.select(inputs, outputs, inputs) # 这里判断的是有没有客户端进行链接。 for s in readable: # 而后在进行判断是服务端触发的链接仍是客户端触发的连接。 if s is listener: # 接收的消息和客户端的IP端口 print(s) connection, client_address = s.accept() print('client:', connection, client_address) # 设置为非阻塞模式。 connection.setblocking(0) # 将客户端链接也加入到inputs监听列表中。 inputs.append(connection) # 加入到要发送的消息队列中。 message_queues[connection] = queue.Queue() else: # 这是客户端发送消息触发的请求。 data = s.recv(1024) if data != b'?' and data != b'': print('客户端{}发送了{}消息', s.getpeername(), data.decode('utf-8')) # 将接收到的消息须要进行回复的答案。放到对应的消息队列中。 print(zen_utils.aphorisms.get(data,b'')) message_queues[s].put(zen_utils.aphorisms.get(data,b'')) if s not in outputs: outputs.append(s) else: print("一个客户端断开了链接", client_address) # 输出端不在监听。 if s in outputs: outputs.remove(s) # 输入端再也不监听 inputs.remove(s) # 关闭这个套接字。 s.close() # 删除消息队列中的消息 del message_queues[s] # 下边是处理输出。 for s in writeable: try: message_queue = message_queues.get(s) sent_data = '' if message_queue is not None: # 若是消息队列为空,不阻塞 sent_data = message_queue.get_nowait() else: # 这里触发的客户端关闭链接。 print('客户端关闭链接') except queue.Empty: # 客户端发送完了消息。 print('%s' % s.getpeername()) outputs.remove(s) else: if sent_data != '': s.sendall(sent_data) else: print('客户端关闭链接') # 处理异常状况。 for s in errorinfo: print('有一个异常客户端的链接', s.getpeername()) inputs.remove(s) if s in outputs: outputs.remove(s) s.close() del message_queues[s] time.sleep(1)if __name__ == '__main__': address = zen_utils.parse_command_line('获取IP端口') listener = zen_utils.create_srv_socket(address) # 将定义好的一个套接字传入到列表中。 inputs = [listener] # 处理要发送的数据。 outputs = [] # 要发送的数据 message_queues = {} serve(listener,inputs,outputs,message_queues)