文件上传的讲解:
1 import subprocess 2 3 res=subprocess.Popen("dir", 4 shell=True, 5 stderr=subprocess.PIPE, 6 stdout=subprocess.PIPE) 7 8 9 print(res.stdout.read().decode("gbk"))
1 import socket 2 import os 3 import json #序列化对象 : 把字典 列表变成字符串 4 5 sock=socket.socket() 6 sock.connect(("127.0.0.1",8800)) 7 8 9 while 1 : 10 cmd=input("请输入命令:") # put 111.jpg 11 12 action,filename=cmd.strip().split(" ") 13 filesize=os.path.getsize(filename) 14 15 file_info={ 16 "action": action, 17 "filename": filename, 18 "filesize": filesize, 19 } 20 file_info_json=json.dumps(file_info).encode("utf8") 21 sock.send(file_info_json) 22 23 # 确认服务端接收到了文件信息 24 code=sock.recv(1024).decode("utf8") 25 if code=="200": 26 # 发送文件数据 27 with open(filename,"rb") as f: 28 for line in f: 29 sock.send(line) 30 else: 31 print("服务器异常!") 32 33 34 ''' 35 36 37 '{.....}' 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' 38 39 40 41 42 '''
对上传的文件进行加密校验:
1 import struct 2 import socket 3 import json 4 import hashlib 5 6 sock=socket.socket() 7 sock.bind(('127.0.0.1',8800)) 8 sock.listen(5) 9 10 11 12 while 1: 13 print("server is working....") 14 conn,addr= sock.accept() 15 while 1: 16 17 # 接收json的打包长度 18 file_info_length_pack=conn.recv(4) 19 file_info_length=struct.unpack("i",file_info_length_pack)[0] 20 21 # 接收json字符串 22 file_info_json=conn.recv(file_info_length).decode("utf8") 23 file_info=json.loads(file_info_json) 24 25 action=file_info.get("action") 26 filename=file_info.get("filename") 27 filesize=file_info.get("filesize") 28 29 # 循环接收文件 30 md5=hashlib.md5() 31 with open("put/"+filename,"wb") as f: 32 recv_data_length=0 33 while recv_data_length<filesize: 34 data=conn.recv(1024) 35 recv_data_length+=len(data) 36 f.write(data) 37 # MD5摘要 38 md5.update(data) 39 print("文件总大小:%s,已成功接收%s"%(filesize,recv_data_length)) 40 41 print("接收成功!") 42 conn.send(b"OK") 43 print(md5.hexdigest()) 44 md5_val=md5.hexdigest() 45 client_md5=conn.recv(1024).decode("utf8") 46 if md5_val==client_md5: 47 conn.send(b"203") 48 else: 49 conn.send(b"204")
import socket import os import json import struct import hashlib sock=socket.socket() sock.connect(("127.0.0.1",8800)) while 1 : cmd=input("请输入命令:") # put 111.jpg action,filename=cmd.strip().split(" ") filesize=os.path.getsize(filename) file_info={ "action": action, "filename": filename, "filesize": filesize, } file_info_json=json.dumps(file_info).encode("utf8") ret=struct.pack("i",len(file_info_json)) # 发送 file_info_json的打包长度 sock.send(ret) # 发送 file_info_json字节串 sock.send(file_info_json) # 发送 文件数据 md5=hashlib.md5() with open(filename,"rb") as f: for line in f: sock.send(line) md5.update(line) data=sock.recv(1024) print(md5.hexdigest()) md5_val=md5.hexdigest() sock.send(md5_val.encode("utf8")) is_valid=sock.recv(1024).decode('utf8') if is_valid=="203": print("文件完整!") else: print("文件上传失败!")
重要模块 socketserver
内部使用IO多路复合,以及多线程、多进程,从而实现并发处理多个客户端请求的服务器
ThreadingTCPServer
ThreadingTCPServer实现的Soket服务器内部会为每个client创建一个 “线程”,该线程用来和客户端进行交互
1、ThreadingTCPServer基础
使用ThreadingTCPServer:
- 创建一个继承自 SocketServer.BaseRequestHandler 的类
- 类中必须定义一个名称为 handle 的方法
- 启动ThreadingTCPServer
import SocketServer class MyServer(SocketServer.BaseRequestHandler): def handle(self): # print self.request,self.client_address,self.server conn = self.request conn.sendall('欢迎致电 10086,请输入1xxx,0转人工服务.') Flag = True while Flag: data = conn.recv(1024) if data == 'exit': Flag = False elif data == '0': conn.sendall('通过可能会被录音.balabala一大推') else: conn.sendall('请重新输入.') if __name__ == '__main__': server = SocketServer.ThreadingTCPServer(('127.0.0.1',8009),MyServer) server.serve_forever() SocketServer实现服务器
#!/usr/bin/env python # -*- coding:utf-8 -*- import socket ip_port = ('127.0.0.1',8009) sk = socket.socket() sk.connect(ip_port) sk.settimeout(5) while True: data = sk.recv(1024) print 'receive:',data inp = raw_input('please input:') sk.sendall(inp) if inp == 'exit': break sk.close() 客户端
SocketServer的ThreadingTCPServer之所以可以同时处理请求得益于 select 和 os.fork 两个东西,其实本质上就是在服务器端为每一个客户端创建一个进程,当前新创建的进程用来处理对应客户端的请求,所以,可以支持同时n个客户端链接(长连接)