简单版
服务端
#!/usr/bin/env python # _*_ coding:utf-8 _*_ # Author:Mr.yang import socket import struct import os import json import subprocess share_dir=r'E:Moudule_14.网络编程5.文件传输servershare' ''' 相对于简单版的优化 1.报头信息少 2.struct的i格式有限制 ''' def run(): phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM) phone.bind(('127.0.0.1',8080)) phone.listen(5) print('setting...') while True: # 链接循环 conn,A = phone.accept() while True: # 通信循环 try: #1.接收数据 res = conn.recv(8096) #b'get a.txt' print('客户端数据:',res) #2.解析命令,提取相应命令参数 cmds = res.decode('utf-8').split() #['get','a.txt'] filename = cmds[1] #3.以读的方式打开文件,读取文件内容发送给客户端 #第一步: 制定固定长度的报头 header_dic={ 'filename': filename, #'filename':'a.txt' 'md5':'xxdxxx', 'file_size':os.path.getsize(r'%s/%s'%(share_dir,filename)) #os.path.getsize('E:Moudule_14.网络编程5.文件传输serversharea.txt') } header_json=json.dumps(header_dic) header_bytes = header_json.encode('utf-8') #第二步:先发报头的长度 conn.send(struct.pack('i',len(header_bytes))) #第三步:再发报头 conn.send(header_bytes) #第四步: 在发送真实的数据 with open('%s/%s'%(share_dir,filename),'rb') as f: # conn.send(f.read()) 文件非常大的话,全部读出来,就会非常占机器的内存 for line in f: conn.send(line) except ConnectionResetError: break conn.close phone.close()
客户端
#!/usr/bin/env python # _*_ coding:utf-8 _*_ # Author:Mr.yang ''' recv不能设置数值特别大的原因: 1.在接收文件的时候可能超过指定数值 2.自己的操作系统的缓存不能无限大,最大也不能超过操作系统的缓存 ''' import socket import struct import json download_dir = r'E:Moudule_14.网络编程5.文件传输clientdownload' phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM) phone.connect(('127.0.0.1',8080)) while True: #1.发命令 cmd = input('>>:').strip() #get a.txt if not cmd:continue phone.send(cmd.encode('utf-8')) #2.以写的方式打开一个新文件,接收服务端发来的文件的内容,写入到客户的新文件中 #第一步: 先收报头的长度 obj = phone.recv(4) header_size = struct.unpack('i',obj)[0] #第二步: 再收报头 header_bytes = phone.recv(header_size) #第三步: 从报头中解析出对真实数据的描述信息 header_json = header_bytes.decode('utf-8') header_dic = json.loads(header_json) ''' header_dic={ 'filename': filename, #'filename':'a.txt' 'md5':'xxdxxx', 'file_size':os.path.getsize(filename) } ''' print(header_dic) total_size = header_dic['file_size'] filename = header_dic['filename'] #第四步: 接收真实的数据 with open('%s/%s'%(download_dir,filename),'wb') as f: #用写的方式写,就会清空之前以读的模式的文件 recv_size=0 while recv_size < total_size: line = phone.recv(1024) f.write(line) recv_size += len(line) print('总大小:%s 已下载大小:%s'%(total_size,recv_size )) phone.close()
优化版
服务端
import socket import struct import os import json import subprocess share_dir=r'E:Moudule_14.网络编程5.文件传输优化版servershare' ''' 相对于简单版的优化 1.报头信息少 2.struct的i格式有限制 ''' def get(conn,cmds): filename = cmds[1] # 3.以读的方式打开文件,读取文件内容发送给客户端 # 第一步: 制定固定长度的报头 header_dic = { 'filename': filename, # 'filename':'a.txt' 'md5': 'xxdxxx', 'file_size': os.path.getsize(r'%s/%s' % (share_dir, filename)) # os.path.getsize('E:Moudule_14.网络编程5.文件传输serversharea.txt') } header_json = json.dumps(header_dic) header_bytes = header_json.encode('utf-8') # 第二步:先发报头的长度 conn.send(struct.pack('i', len(header_bytes))) # 第三步:再发报头 conn.send(header_bytes) # 第四步: 在发送真实的数据 with open('%s/%s' % (share_dir, filename), 'rb') as f: # conn.send(f.read()) 文件非常大的话,全部读出来,就会非常占机器的内存 for line in f: conn.send(line) def run(): phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM) phone.bind(('127.0.0.1',8080)) phone.listen(5) print('setting...') while True: # 链接循环 conn,A = phone.accept() while True: # 通信循环 try: #1.接收数据 res = conn.recv(8096) #b'get a.txt' print('客户端数据:',res) #2.解析命令,提取相应命令参数 cmds = res.decode('utf-8').split() #['get','a.txt'] if cmds[0] == 'get': get(conn,cmds) except ConnectionResetError: break conn.close phone.close() if __name__ == '__main__': run()
客户端
import socket import struct import json download_dir = r'E:Moudule_14.网络编程5.文件传输优化版clientdownload' def get(phone,cmds): # 2.以写的方式打开一个新文件,接收服务端发来的文件的内容,写入到客户的新文件中 # 第一步: 先收报头的长度 obj = phone.recv(4) header_size = struct.unpack('i', obj)[0] # 第二步: 再收报头 header_bytes = phone.recv(header_size) # 第三步: 从报头中解析出对真实数据的描述信息 header_json = header_bytes.decode('utf-8') header_dic = json.loads(header_json) ''' header_dic={ 'filename': filename, #'filename':'a.txt' 'md5':'xxdxxx', 'file_size':os.path.getsize(filename) } ''' print(header_dic) total_size = header_dic['file_size'] filename = header_dic['filename'] # 第四步: 接收真实的数据 with open('%s/%s' % (download_dir, filename), 'wb') as f: # 用写的方式写,就会清空之前以读的模式的文件 recv_size = 0 while recv_size < total_size: line = phone.recv(1024) f.write(line) recv_size += len(line) print('总大小:%s 已下载大小:%s' % (total_size, recv_size)) def run(): phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM) phone.connect(('127.0.0.1',8080)) while True: #1.发命令 inp = input('>>:').strip() #get a.txt if not inp:continue phone.send(inp.encode('utf-8')) cmds = inp.split() #['get';a.txt] if cmds[0] == 'get': get(phone,cmds) phone.close() if __name__ == '__main__': run()