socketserver
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 服务端下载到客户端
未完...