非阻塞IO模型解决阻塞IO(socket例子)
#方法:sk.setblocking(False) #服务器端: import socket sk=socket.socket() sk.setblocking(False) sk.bind(('127.0.0.1',8080)) sk.listen() #定义空列表用于存放各个conn Conn_List = [] #定义删除列表用于删除Conn_List中断开连接的客户端conn Conn_Del = [] while 1: try: conn,addr = sk.accept() #如果是阻塞IO,此时程序会一直在这里等待 Conn_List.append(conn) #将监听到的conn对象放到conn列表中,即为多客户端连接 except BlockingIOError: '''如果try中没有客户端连接,则执行该代码块,判断客户端是否向服务器发送数据''' #遍历conn列表,看看有没有客户端发送数据 for conn in Conn_List: try: #尝试接收数据 info = conn.recv(1024).decode('utf-8') #注意!如果客户端正常关闭,即客户端执行了close,服务器会接收到一个空 if not info: #如果收到空,证明客户端断开连接,将该conn添加到删除列表中,用于后面删除Conn_List中对应的conn Conn_Del.append(conn) print('客户端已经断开连接了') #在服务器中关闭对应的conn conn.close() else: '''服务器逻辑层''' # 如果收到客户端的数据,逻辑层返回数据给客户端 print('这是接收到来自客户端{}的数据:{}'.format(conn,info)) #返回数据给客户端(例如将客户端的数据小写转为大写返回给客户端) conn.send(info.upper().encode('utf-8')) except BlockingIOError: '''如果本次循环中该conn没有发送数据,则执行该代码块,即对下一个conn通信''' continue except ConnectionResetError: '''如果本次循环中该conn强制退出,则不执行任何操作''' pass #删除列表删除Conn_List中已经正常断开连接的客户端conn if Conn_Del: for conn in Conn_Del: Conn_List.remove(conn) #在删除完正常关闭链接的客户端后,应该把删除列表清空,否则会报错 Conn_Del = [] #客户端: import socket sk = socket.socket() sk.connect(('127.0.0.1',8080)) while 1: msg_s = input('>>>') if not msg_s:continue if msg_s == 'q':break sk.send(msg_s.encode('utf-8')) print(sk.recv(1024).decode('utf-8')) sk.close()