socketserver
SocketServer内部使用 IO多路复用 以及 “多线程” 和 “多进程” ,从而实现并发处理多个客户端请求的Socket服务端。即:每个客户端请求连接到服务器时,Socket服务端都会在服务器是创建一个“线程”或者“进程” 专门负责处理当前客户端的所有请求。
特点:
socketserver自带多线程、多进程
socketserver中的两个类,可以解决两个问题:
server类:保证一直运行提供服务(连接循环)
request类:可以基于一个连接进行通信循环
- 一 简单示例
- 二 简单示例二
- 三 模拟上传、下载功能
- 1 客户端上传到服务端
- 2 服务端下载到客户端
一 简单示例
客户端输入,服务端返回大写
ps:基于TCP的socketserver,实现了并发
server:
import socketserver class MyFTP(socketserver.BaseRequestHandler): def handle(self): while True: data = self.request.recv(1024) self.request.send(data.upper()) if __name__ == '__main__': obj = socketserver.ThreadingTCPServer(('127.0.0.1', 8484), MyFTP) obj.serve_forever()
建立连接:
1.实例化连接类socketserver.ThreadingTCPServer(('172.0.0.1',8080),FTPserver)
执行通信循环:
2.永远接收连接obj.serve_forever()
通信:
1.MyServer必须继承socketserver.BaseRequestHandler
类
2.类中必须有方法handle方法
3.self.request.recv()
和self.request.send()
(self.request.sendall()
)完成发送和接收数据
client:
import socket ip_port = ('127.0.0.1', 8484) sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sk.connect(ip_port) while True: msg = input('>>:').strip() if msg == '': continue sk.send(msg.encode('utf-8')) data = sk.recv(1024) print(data)
二 简单示例二
模拟客房服务
server:
import socketserver class MyServer(socketserver.BaseRequestHandler): def handle(self): # print(self.request, self.client_address, self.server) conn = self.request conn.sendall('欢迎致电 小红足疗,学生请按1,白领请按2,...,如需帮助请按0.'.encode('utf8')) Flag = True while Flag: data = conn.recv(1024) data = data.decode('utf8') if data == 'exit': Flag = False elif data == '0': conn.sendall('您的通过可能会被录音...为您上钟的是...'.encode('utf8')) else: conn.sendall('请重新输入.'.encode('utf8')) if __name__ == '__main__': server = socketserver.ThreadingTCPServer(('127.0.0.1', 8080), MyServer) server.serve_forever()
client:
import socket ip_port = ('127.0.0.1', 8080) sk = socket.socket() sk.connect(ip_port) sk.settimeout(5) while True: data = sk.recv(1024) print('receive:', data.decode('utf8')) inp = input('please input:') sk.sendall(inp.encode('utf8')) if inp == 'exit': break sk.close()
三 模拟上传、下载功能
基于TCP的socketserver,实现并发的上传、下砸功能
1 客户端上传到服务端
server:
import socketserver import struct import json import subprocess import os class MYTCPServer(socketserver.BaseRequestHandler): max_packet_size = 8192 coding='utf-8' file_path = os.path.dirname(os.path.dirname(__file__)) server_dir='file_upload' def handle(self): while True: while True: try: head_struct = self.request.recv(4) if not head_struct:break head_len = struct.unpack('i', head_struct)[0] head_json = self.request.recv(head_len).decode(self.coding) head_dic = json.loads(head_json) print(head_dic) #head_dic={'cmd':'put','filename':'a.txt','filesize':123123} cmd=head_dic['cmd'] if hasattr(self,cmd): func=getattr(self,cmd) func(head_dic) except Exception: break def put(self,args): file_path=os.path.normpath(os.path.join( self.file_path, self.server_dir, args['filename'] )) filesize=args['filesize'] recv_size=0 print('----->',file_path) with open(file_path,'wb') as f: while recv_size < filesize: recv_data=self.request.recv(self.max_packet_size) f.write(recv_data) recv_size+=len(recv_data) print('recvsize:%s filesize:%s' %(recv_size,filesize)) if __name__ == '__main__': obj = socketserver.ThreadingTCPServer(('127.0.0.1',8586),MYTCPServer) obj.serve_forever()
client:
import socket import struct import json import os class MYTCPClient: address_family = socket.AF_INET socket_type = socket.SOCK_STREAM allow_reuse_address = False max_packet_size = 8192 coding='utf-8' request_queue_size = 5 def __init__(self, server_address, connect=True): self.server_address=server_address self.socket = socket.socket(self.address_family, self.socket_type) if connect: try: self.client_connect() except: self.client_close() raise def client_connect(self): self.socket.connect(self.server_address) def client_close(self): self.socket.close() def run(self): while True: inp=input(">>: ").strip() if not inp:continue l=inp.split() cmd=l[0] if hasattr(self,cmd): func=getattr(self,cmd) func(l) def put(self,args): cmd=args[0] filename=args[1] if not os.path.isfile(filename): print('file:%s is not exists' %filename) return else: filesize=os.path.getsize(filename) head_dic={'cmd':cmd,'filename':os.path.basename(filename),'filesize':filesize} print(head_dic) head_json=json.dumps(head_dic) head_json_bytes=bytes(head_json,encoding=self.coding) head_struct=struct.pack('i',len(head_json_bytes)) self.socket.send(head_struct) self.socket.send(head_json_bytes) send_size=0 with open(filename,'rb') as f: for line in f: self.socket.send(line) send_size+=len(line) print(send_size) print(line) else: print('upload successful') client=MYTCPClient(('127.0.0.1',8586)) client.run()
2 服务端下载到客户端
未完...
来源:https://www.cnblogs.com/sunqim16/p/6808327.html