socketsoerver类的五大类型之间的联系:
日常主要用到的是以下这两个类型,但是,你会发现这两个类型,并没法实现我们要的多客户端连接,只等前一个连接结束,后一个连接才可以开始。
socketserver.TCPServer:是用于TCP连接
socketserver.UDPServer:是用于UDP连接
要想实现多客户端连接,则需要用以下两个类型
socketserver.ThreadingTCPServer:支持并发连接,即每收到一个连接请求,都会派出一个小弟(也就是创建一个线程)去连接。
ocketserver.ThreadingUDPServer:也是通过线程来实现高并发的
socketserver类的基本用法步骤:(以TCP连接为例子)
1 import socketserver 2 import subprocess 3 #第一步:创建一个类,该类需要继承socketserver的基础类BaseRequestHandler, 4 #同时,需要重写该基础类的handle()方法 5 class myTCPHandler(socketserver.BaseRequestHandler): 6 #重写handle方法 7 def handle(self): 8 #这里是实现接收跟发送的代码 9 pass 10 11 if __name__=='__main__': 12 host,port='localhost',9999 13 #第二步:创建一个socketserver类中其中一种类型的实例 14 #同时,把元组(IP,port),以及第一步创建的类,传给这个实例 15 server=socketserver.ThreadingTCPServer((host,port),myTCPHandler) 16 #第三步:调用server_forever()/handle_request()方法来处理请求 17 #多连接请求 18 server.serve_forever() 19 #server_forever()等价于socket类中以下这部分代码 20 #while True: 21 # con, addr = server_sock.accept() 22 23 #单链接请求: 24 handle_request() 25 #等价于socket类以下这句代码 26 #con, addr = server_sock.accept()
完整例子如下:(模拟远程执行cmd命令)
1 #服务端 2 # -*-coding:utf-8 -*- 3 import socketserver 4 import subprocess 5 class myTCPHandler(socketserver.BaseRequestHandler): 6 def handle(self): 7 while True: 8 self.data=self.request.recv(1024).strip() 9 data=subprocess.Popen(self.data.decode('utf-8'),shell=True,stdout=subprocess.PIPE,stdin=subprocess.PIPE,stderr=subprocess.PIPE) 10 stdout=data.stdout.read() 11 print('----------------') 12 print('输出',stdout) 13 # stdin=data.stdin.read() 14 stderr=data.stderr.read() 15 print('异常输出',stderr) 16 if len(stdout)==0: 17 l=len(stderr) 18 self.request.sendall(str(l).encode()) 19 self.request.sendall(stderr) 20 else: 21 l = len(stderr) 22 self.request.sendall(str(l).encode()) 23 self.request.sendall(stdout) 24 25 if __name__=='__main__': 26 host,port='localhost',9999 27 server=socketserver.ThreadingTCPServer((host,port),myTCPHandler) 28 server.serve_forever()
29 #客户端 30 # -*-coding:utf-8 -*- 31 import socket 32 33 c=socket.socket(socket.AF_INET,socket.SOCK_STREAM) 34 ip_port=('localhost',9999) 35 c.connect(ip_port) 36 while True: 37 cmd=input('cmd>>:') 38 c.send(cmd.encode()) 39 data_len=c.recv(1024).decode('utf-8') 40 41 print('客户端发送过来的数据长度是:'+data_len) 42 i=int(data_len)/1024 43 print(i) 44 data=b'' 45 while i+1>=1: 46 data+=c.recv(1024) 47 i-=1 48 # print(n,type(n)) 49 # data=c.recv(1024) 50 print(data.decode('gbk'))
UDP跟TCP使用socketserver的区别;
UDP: 接收数据: data= self.request[0] 获取套接字对象 udp_s = self.request[1] 获取IP_port: add = self.client_address TCP: data=self.request.recv(1024) 直接用self.request就可以发数据,收数据
具体例子如下:
服务端
1 # -*-coding:utf-8 -*- 2 import socketserver 3 import subprocess 4 class UDPhandle(socketserver.BaseRequestHandler): 5 def handle(self): 6 7 while True: 8 cmd = self.request[0] 9 udp_s = self.request[1] 10 add = self.client_address 11 cmd_data = subprocess.Popen(cmd.decode('utf-8'), shell=True, stdin=subprocess.PIPE, stderr=subprocess.PIPE, 12 stdout=subprocess.PIPE) 13 stderr = cmd_data.stderr.read() 14 stdout = cmd_data.stdout.read() 15 if not stderr: 16 d = str(len(stdout)) 17 udp_s.sendto(d.encode(), add) 18 udp_s.sendto(stdout, add) 19 else: 20 d = str(len(stderr)) 21 udp_s.sendto(d.encode(), add) 22 udp_s.sendto(stderr, add) 23 24 if __name__=='__main__': 25 udp_s=socketserver.ThreadingUDPServer(('localhost',1111),UDPhandle) 26 udp_s.serve_forever()
客户端
# -*-coding:utf-8 -*- import socket udp_c=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) ip_port=('localhost',1111) while True: msg=input('>>:').strip() if not msg: continue udp_c.sendto(msg.encode(),ip_port) size=int(udp_c.recv(1024)) print(size) backPmsg,addr=udp_c.recvfrom(size) print(backPmsg.decode('gbk'))