python 之 并发编程(非阻塞IO模型、I/O多路复用、socketserver的使用)
9.16 非阻塞IO模型
cpu占用率过高
服务端:
from socket import * import time s = socket() s.bind(('127.0.0.1',8080)) s.listen(5) s.setblocking(False) #使accept接收不到连接时不在阻塞 r_list=[] while True: try: conn, addr = s.accept() r_list.append(conn) except BlockingIOError: # time.sleep(3) #print('可以去干其他的活了') #print('rlist: ',len(r_list)) for conn in r_list: try: data=conn.recv(1024) conn.send(data.upper()) except BlockingIOError: continue
客户端;
from socket import * import os client = socket() client.connect(('127.0.0.1', 8080)) while True: data='%s say hello' %os.getpid() client.send(data.encode('utf-8')) res=client.recv(1024) print(res.decode('utf-8'))
9.17 I/O多路复用
服务端:
from socket import * import select s = socket() s.bind(('127.0.0.1',8080)) s.listen(5) s.setblocking(False) #使accept接收不到连接时不在阻塞 # print(s) r_list=[s,] w_list=[] w_data={} while True: print('被检测r_list: ',len(r_list)) print('被检测w_list: ',len(w_list)) #rl中是r_list中建立连接的套接字对象 rl,wl,xl=select.select(r_list,w_list,[],) #r_list=[server,conn] # print('rl: ',len(rl)) #rl=[conn,] # print('wl: ',len(wl)) # 收消息 for r in rl: #r=conn if r == s: conn,addr=r.accept() r_list.append(conn) else: try: data=r.recv(1024) if not data: r.close() r_list.remove(r) continue # r.send(data.upper()) w_list.append(r) w_data[r]=data.upper() except ConnectionResetError: r.close() r_list.remove(r) continue # 发消息 for w in wl: w.send(w_data[w]) w_list.remove(w) w_data.pop(w)
客户端:
from socket import * import os client = socket() client.connect(('127.0.0.1', 8080)) while True: data='%s say hello' %os.getpid() client.send(data.encode('utf-8')) res=client.recv(1024) print(res.decode('utf-8'))
9.18 socketserver的使用
9.181 基于tcp的socketserver
服务端:
import socketserver # 通信循环 class MytcpHandler(socketserver.BaseRequestHandler): def handle(self): while True: try: data = self.request.recv(1024) # 1024 接收数据的最大限制 if not data: break # 针对linux系统 self.request.send(data.upper()) # 注意:收发都是以bytes为单位 except ConnectionResetError: break self.request.close() if __name__ == '__main__': #连接循环 server=socketserver.ThreadingTCPServer(('127.0.0.1',8080),MytcpHandler) server.serve_forever() print(server.server_address) print(server.RequestHandlerClass) print(server.socket)
客户端:
import socket client=socket.socket(socket.AF_INET,socket.SOCK_STREAM) client.connect(('127.0.0.1',8080)) while True: msg=input('>>: ').strip() client.send(msg.encode('utf-8')) data=client.recv(1024) print(data.decode('utf-8')) client.close()
9.182 基于udp的socketserver
服务端:
import socketserver # 通信循环 class MyUDPHandler(socketserver.BaseRequestHandler): def handle(self): print(self.request)#(b'13404 hello', <socket.socket fd=460, family=AddressFamily.AF_INET, res=self.request[0]#type=SocketKind.SOCK_DGRAM, proto=0, laddr=('127.0.0.1', 8080)>) print('客户端发来的数据:',res) self.request[1].sendto(res.upper(),self.client_address) if __name__ == '__main__': #连接循环 server=socketserver.ThreadingUDPServer(('127.0.0.1',8080),MyUDPHandler) server.serve_forever()
客户端:
import socket import os client=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) while True: msg='%s hello' %os.getpid() client.sendto(msg.encode('utf-8'),('127.0.0.1',8080)) res,server_addr=client.recvfrom(1024) print(res)