一、服务端代码:
1 import socket 2 import subprocess 3 import struct 4 import json 5 import os 6 7 phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 8 # phone.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 9 phone.bind(('127.0.0.1', 8081)) # 0-65535:0-1024给操作系统使用10 phone.listen(5)11 12 print('starting......')13 while True: # 链接循环14 conn, client_addr = phone.accept()15 print(client_addr)16 17 while True: # 通信循环18 try:19 # 1、收命令20 res = conn.recv(8096) # b'get a.txt'21 if not res: # 适用于linux操作系统22 break23 24 # 2、解析命令,提取相应命令参数25 cmds = res.decode('utf-8').split() # ['get', 'a.txt']26 filename = cmds[1]27 # 3、以读的方式打开文件,读取文件内容发送到客户端28 29 # 第一步:制作固定长度的报头30 header_dic = {31 'filename': filename,32 'md5': 'xxdxx',33 'file_size': os.path.getsize(filename)34 }35 36 header_json = json.dumps(header_dic)37 header_bytes = header_json.encode('utf-8')38 39 # 第二步:先发送报头的长度40 conn.send(struct.pack('i', len(header_bytes)))41 42 # 第三步:把包头发送给客户端43 conn.send(header_bytes)44 45 # 第三步:再发送真实的数据46 with open(filename, 'rb') as f:47 # conn.send(f.read())48 for line in f:49 conn.send(line)50 51 except ConnectionResetError: # 适用于Windows操作系统52 break53 54 conn.close()55 56 phone.close()
二、客户端代码:
1 import socket 2 import struct 3 import json 4 5 6 phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 7 8 phone.connect(('127.0.0.1', 8081)) 9 10 while True:11 # 1、发命令12 cmd = input('>>:').strip() # get a.txt13 if not cmd:14 continue15 phone.send(cmd.encode('utf-8'))16 17 # 2、以写的方式打开一个新文件,接收服务器端发来的文件内容写入客户的新文件18 19 # 第一步:先收报头的长度20 obj = phone.recv(4)21 header_size = struct.unpack('i', obj)[0]22 23 # 第二步:再收报头24 header_bytes = phone.recv(header_size)25 26 # 第三步:从报头中解析出对真实数据的描述信息27 header_json = header_bytes.decode('utf-8')28 header_dic = json.loads(header_json)29 print(header_dic)30 total_size = header_dic['file_size']31 filename = header_dic['filename']32 33 # 第四步: 接收真实的数据34 with open(filename, 'wb') as f:35 recv_size = 036 while recv_size < total_size:37 line = phone.recv(1024)38 f.write(line)39 recv_size += len(line)40 41 42 phone.close()
先启动服务端,再启动客户端,然后在客户端执行 get 1.txt, get test.py 都显示下载成功:
客户端打印字典信息为:
1 >>:get 1.txt2 { 'filename': '1.txt', 'md5': 'xxdxx', 'file_size': 8}3 >>:get test.py4 { 'filename': 'test.py', 'md5': 'xxdxx', 'file_size': 60}5 >>:
以上代码已经实现了客户端从服务端下载文件的功能,如果想把数据从客户端上传到服务端,则把服务端和客户端代码
做相应调整即可。
如果server提供下载文件夹share,client指定下载文件夹download,
客户端和服务端代码改为:
1 客户端代码: 2 import socket 3 import struct 4 import json 5 6 download_dir = r'C:\Users\xu516\PycharmProjects\Python全栈开发\第三模块\网络编程\06_文件传输\client\download' 7 phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 8 9 phone.connect(('127.0.0.1', 8081)) 10 11 while True: 12 # 1、发命令 13 cmd = input('>>:').strip() # get a.txt 14 if not cmd: 15 continue 16 phone.send(cmd.encode('utf-8')) 17 18 # 2、以写的方式打开一个新文件,接收服务器端发来的文件内容写入客户的新文件 19 20 # 第一步:先收报头的长度 21 obj = phone.recv(4) 22 header_size = struct.unpack('i', obj)[0] 23 24 # 第二步:再收报头 25 header_bytes = phone.recv(header_size) 26 27 # 第三步:从报头中解析出对真实数据的描述信息 28 header_json = header_bytes.decode('utf-8') 29 header_dic = json.loads(header_json) 30 print(header_dic) 31 total_size = header_dic['file_size'] 32 filename = header_dic['filename'] 33 34 # 第四步: 接收真实的数据 35 with open('%s\%s' % (download_dir, filename), 'wb') as f: 36 recv_size = 0 37 while recv_size < total_size: 38 line = phone.recv(1024) 39 f.write(line) 40 recv_size += len(line) 41 print('总大小:%s 已下载大小:%s' % (total_size, recv_size)) 42 43 44 phone.close() 45 46 服务端代码: 47 import socket 48 import subprocess 49 import struct 50 import json 51 import os 52 53 share_dir = r'C:\Users\xu516\PycharmProjects\Python全栈开发\第三模块\网络编程\06_文件传输\server\share' 54 phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 55 # phone.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 56 phone.bind(('127.0.0.1', 8081)) # 0-65535:0-1024给操作系统使用 57 phone.listen(5) 58 59 print('starting......') 60 while True: # 链接循环 61 conn, client_addr = phone.accept() 62 print(client_addr) 63 64 while True: # 通信循环 65 try: 66 # 1、收命令 67 res = conn.recv(8096) # b'get a.txt' 68 if not res: # 适用于linux操作系统 69 break 70 71 # 2、解析命令,提取相应命令参数 72 cmds = res.decode('utf-8').split() # ['get', 'a.txt'] 73 filename = cmds[1] 74 # 3、以读的方式打开文件,读取文件内容发送到客户端 75 76 # 第一步:制作固定长度的报头 77 header_dic = { 78 'filename': filename, 79 'md5': 'xxdxx', 80 'file_size': os.path.getsize('%s\%s' % (share_dir, filename)) 81 } 82 83 header_json = json.dumps(header_dic) 84 header_bytes = header_json.encode('utf-8') 85 86 # 第二步:先发送报头的长度 87 conn.send(struct.pack('i', len(header_bytes))) 88 89 # 第三步:把包头发送给客户端 90 conn.send(header_bytes) 91 92 # 第三步:再发送真实的数据 93 with open('%s\%s' % (share_dir, filename), 'rb') as f: 94 # conn.send(f.read()) 95 for line in f: 96 conn.send(line) 97 98 except ConnectionResetError: # 适用于Windows操作系统 99 break100 101 conn.close()102 103 phone.close()
客户端下载 get test.py 运行结果为:
1 >>:get test.py2 { 'filename': 'test.py', 'md5': 'xxdxx', 'file_size': 60}3 总大小:60 已下载大小:604 >>: