老师的博客:
server端
import json import struct import json import struct import socket import os sk = socket.socket() sk.bind(('192.168.43.155',8080)) sk.listen() conn,addr = sk.accept() dic_len = conn.recv(4) # 4个字节 数字的大小 dic_len = struct.unpack('i',dic_len)[0] content = conn.recv(dic_len).decode('utf-8') # 70 content_dic = json.loads(content) if content_dic['operate'] == 'upload': with open(content_dic['filename'],'wb') as f: while content_dic['filesize']: file = conn.recv(1024) f.write(file) content_dic['filesize'] -= len(file) elif content_dic['operate'] == 'download': file_path=content_dic['path'] file_name=os.path.basename(file_path) file_size=os.path.getsize(file_path) dic_from={'file_size':file_size,'file_name':file_name} dic_from=json.dumps(dic_from).encode('utf-8') dic_lenth=struct.pack('i',len(dic_from)) print(dic_lenth,type(dic_lenth)) conn.send(dic_lenth + dic_from) with open(file_path,mode='rb') as f: while file_size>0: ret=f.read(1024) conn.send(ret) file_size -= 1024 print('传输完成') else: print('错了') conn.close() sk.close()
client端
import os import json import struct import socket sk = socket.socket() sk.connect(('192.168.43.155',8080)) def get_filename(file_path): filename = os.path.basename(file_path)#os.path.basename(path) 返回path最后的文件名。 # 如果path以/或\结尾,那么就会返回空值。即os.path.split(path)的第二个元素 return filename #选择 操作 operate = ['upload','download'] for num,opt in enumerate(operate,1):#枚举函数,第一个参数是对象,第二是是下标的开始计数 print(num,opt) num = int(input('请输入您要做的操作序号 : ')) if num == 1: '''上传操作''' file_path = input('请输入要上传的文件路径 : ') file_size = os.path.getsize(file_path) # 获取文件大小 file_name = get_filename(file_path)#获取文件路径 dic = {'operate': 'upload', 'filename': file_name,'filesize':file_size} str_dic = json.dumps(dic).encode('utf-8') ret = struct.pack('i', len(str_dic)) # 将字典的大小转换成一个定长(4)的bytes sk.send(ret + str_dic) with open(file_path,'rb') as f: while file_size: content = f.read(1024) sk.send(content) file_size -= len(content) print('上传成功') elif num == 2: '''下载操作''' download_path=input('请输入你要下载的路径') dic=json.dumps({'operate':'download','path':download_path}).encode('utf-8') download_path_unm=struct.pack('i',len(dic)) sk.send(download_path_unm+dic)#发送信息 get_information=sk.recv(4)#接受即将带来的信息的长度 get_information_real=struct.unpack('i',get_information)[0]#转化为真是数字 get_real_information=sk.recv(get_information_real).decode('utf-8')#接受,解压 get_real_information=json.loads(get_real_information) download_file_name=get_real_information['file_name'] download_file_size=get_real_information['file_size'] with open(download_file_name,mode='wb') as f: while download_file_size>0: print(download_file_size) code=sk.recv(1024) f.write(code) download_file_size -= 1024 print('下载成功') sk.close()
说明:
上传老师写的,我自己是吧下载给补充的写了,所以上传和下载的代码应该还可以优化一下。
下面是在写代码中遇到的问题,总结一下:
1.struct中,把数字转化为4的固定长度的bytes类型,所以就不需要再进行encode操作,因为本身就是bytes类型的,而却其编码方式叫特别,只能通过unpack才能转化为数字,记住是int,通过其他方式。例如。gbk。utf-8decode是str类型,但是内容确实空白的·另外关于unpack得到的是个元祖,所以的到的值需要取第0位数,来取到你需要的数字。
2,json模块,由于json是把数据类型给转化为str类型的,所以还需要在进行encode()的操作,来吧其转化为bytes类型的。所以拿到是,应该首先decode()。
3,send的是时候可以采用(内容1+内容2)的形式,表示两次发送的
4,下载上传是必需要把文件的大小拿到,然后采用相等的大小传输,所以需要把文件大小先传输过去,然后在进行同时的收发操作。
5.while循环是,条件应该写成长度<0是结束,因为有很大的情况下,大小-=1024是不可能刚好减到0的,如果为负数的时候,条件还是为真,所以不会终止循环,然后就出不来了。
6,数据传输和接受的时候都是以bytes的方式打开或者写入的,而且在不需要写编码方式,因为传输的有可能是视频。