一、服务端代码为:
1 import socket 2 import subprocess 3 import struct 4 import json 5 import os 6 7 share_dir = r'C:Usersxu516PycharmProjectsPython全栈开发第三模块网络编程 6_文件传输优化版本_写函数servershare' 8 9 10 def get(conn, cmds): 11 filename = cmds[1] 12 # 3、以读的方式打开文件,读取文件内容发送到客户端 13 14 # 第一步:制作固定长度的报头 15 header_dic = { 16 'filename': filename, 17 'md5': 'xxdxx', 18 'file_size': os.path.getsize('%s\%s' % (share_dir, filename)) 19 } 20 21 header_json = json.dumps(header_dic) 22 header_bytes = header_json.encode('utf-8') 23 24 # 第二步:先发送报头的长度 25 conn.send(struct.pack('i', len(header_bytes))) 26 27 # 第三步:把包头发送给客户端 28 conn.send(header_bytes) 29 30 # 第三步:再发送真实的数据 31 with open(r'%s\%s' % (share_dir, filename), 'rb') as f: 32 # conn.send(f.read()) 33 for line in f: 34 conn.send(line) 35 36 37 def run(): 38 phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 39 # phone.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 40 phone.bind(('127.0.0.1', 8081)) # 0-65535:0-1024给操作系统使用 41 phone.listen(5) 42 43 print('starting......') 44 while True: # 链接循环 45 conn, client_addr = phone.accept() 46 print(client_addr) 47 48 while True: # 通信循环 49 try: 50 # 1、收命令 51 res = conn.recv(8096) # b'get a.txt' 52 if not res: # 适用于linux操作系统 53 break 54 55 # 2、解析命令,提取相应命令参数 56 cmds = res.decode('utf-8').split() # ['get', 'a.txt'] 57 if cmds[0] == 'get': 58 get(conn, cmds) 59 60 except ConnectionResetError: # 适用于Windows操作系统 61 break 62 63 conn.close() 64 65 phone.close() 66 67 68 if __name__ == '__main__': 69 run()
二、客户端代码为:
1 import socket 2 import struct 3 import json 4 5 download_dir = r'C:Usersxu516PycharmProjectsPython全栈开发第三模块网络编程 6_文件传输优化版本_写函数clientdownload' 6 7 8 def get(phone, cmds): 9 # 2、以写的方式打开一个新文件,接收服务器端发来的文件内容写入客户的新文件 10 11 # 第一步:先收报头的长度 12 obj = phone.recv(4) 13 header_size = struct.unpack('i', obj)[0] 14 15 # 第二步:再收报头 16 header_bytes = phone.recv(header_size) 17 18 # 第三步:从报头中解析出对真实数据的描述信息 19 header_json = header_bytes.decode('utf-8') 20 header_dic = json.loads(header_json) 21 print(header_dic) 22 total_size = header_dic['file_size'] 23 filename = header_dic['filename'] 24 25 # 第四步: 接收真实的数据 26 with open('%s\%s' % (download_dir, filename), 'wb') as f: 27 recv_size = 0 28 while recv_size < total_size: 29 line = phone.recv(1024) 30 f.write(line) 31 recv_size += len(line) 32 print('总大小:%s 已下载大小:%s' % (total_size, recv_size)) 33 34 35 def put(phone, cmds): 36 pass 37 38 39 def run(): 40 phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 41 phone.connect(('127.0.0.1', 8081)) 42 43 while True: 44 # 1、发命令 45 inp = input('>>:').strip() # get a.txt 46 if not inp: 47 continue 48 phone.send(inp.encode('utf-8')) 49 50 cmds = inp.split() # ['get', 'a.txt'] 51 if cmds[0] == 'get': 52 get(phone, cmds) 53 elif cmds[0] == 'put': 54 put(phone, cmds) 55 56 phone.close() 57 58 59 if __name__ == '__main__': 60 run()
先启动服务端,在启动客户端,在客户端输入get test.py 下载成功:
客户端运行结果为:
1 >>:get test.py 2 {'filename': 'test.py', 'md5': 'xxdxx', 'file_size': 60} 3 总大小:60 已下载大小:60 4 >>: