from concurrent.futures import ThreadPoolExecutorimport socketimport select# select 帮你从一堆连接中找出来需要被处理的连接server = socket.socket()# 重用端口server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)server.bind(("192.168.11.210",9999))server.listen(5)# 设置是否为阻塞 默认阻塞server.setblocking(False)def data_handler(conn): print("一个新连接..") while True: data = conn.recv(1024) conn.send(data.upper())# 需要检测的 是否可读取的列表 (recv就是一个读取操作)rlist = [server,]# 需要检测的 是否写入的列表 (send就是写入操作)wlist = []# 需要发送的数据 目前是因为 我们要把接收的数据在发回去 所以搞了这个东西 正常没有这种需求# 目前客户端与服务器端 交互 是必须客户端发送数据 服务器端才能返回数据 正常没有这种需求dic = {}while True: # 用于检测需要处理的连接 需要不断检测 所以循环 # rl目前可读的客户端列表 wl目前可写的客户端列表 rl,wl,xl = select.select(rlist,wlist,[]) # select默认阻塞 阻塞到任意一个连接可以被处理 print(len(rl)) # 处理可读的socket for c in rl: # 无论是客户端还是服务器只要可读就会执行到这里 if c == server: # 接收客户端的连接请求 (一个读操作) conn,addr = c.accept() # 将新连接也交给select来检测 rlist.append(conn) else:# 不是服务器 就是客户端 客户端可读 可以执行recv try: data = c.recv(1024) if not data: c.close() rlist.remove(c) print("%s 发送 %s" % (c,data.decode("utf-8"))) # 给客户端发送数据 前要保证目前可以发送 将客户端加入检测列表 wlist.append(c) # 正常开发中 不可能必须客户端发送数据过来后 才能 给客户端发送 # 所以这个添加到检测列表的操作 应该建立连接后立即执行 # 要发送的数据 dic[c] = data except ConnectionResetError: # 客户端关闭连接 c.close() rlist.remove(c) # 处理可写的socket for c in wl: print(c) try: c.send(dic[c].upper()) # 删除数据 dic.pop(c) # 从检测列表中删除已发送完成的客户端 wlist.remove(c) except ConnectionResetError: c.close() # 关闭连接 dic.pop(c) # 删除要发送的数据 wlist.remove(c) # 从待检测的列表中删除 except BlockingIOError:#可能缓存满了 发不了 pass
import socketc = socket.socket()c.connect(("192.168.11.210",9999))while True: msg = input(">>>:") if not msg:continue c.send(msg.encode("utf-8")) data = c.recv(1024) print(data.decode("utf-8"))