python_网络编程之端点续传
这个例子分为服务端和客户端,都做了大量的注释,很容易读懂
服务端
##以下代码是梳理思路 # import socketserver # import os #使用os模块的join方法 # import json # cod={'1001':'开始上传','1002':'开始续传'} # class Nbserver(socketserver.BaseRequestHandler): # def handle(self): # while 1: # # 1 , 接受命令 # upload_cmd_bytes=self.request.recv(2048) #最大是8k # # upload_cmd_str=json.loads(upload_cmd_bytes).decode("utf8") #错误的写法 # cmd_dic = json.loads(upload_cmd_bytes.decode("utf8")) #是字节有解码的方法 # # # # 2,获取文件信息 # file_md5=cmd_dic['md5'] # home=r'E:\老男孩课程\mysql_db' # file_mdf_path=os.path.join(home,'zhangzijie',file_md5) # # exist=os.path.exists(file_mdf_path) # if not exist: #不续传 # #我没有这个文件,你开始给我传 # #设计状态码 # response = {'code': 1001} # self.request.sendall(b'1001') # else: # #怎么续传呢?你的告诉客户端我已经有多少了,你已经给我传了多少了,对方才能 # #从断开的那里进行继续传 # #根据文件路径获取大小 # exist_szie=os.stat(file_mdf_path).st_size # #定义一个协议 # response={'code':1002,'size':exist_szie} # self.request.sendall(json.dumps(response).encode("utf-8")) # self.request.sendall(b'1002') # # # # print(cmd_dic) # # # server=socketserver.ThreadingTCPServer(('127.0.0.1',8001),Nbserver) # server.serve_forever() ########################################################################################### # 下面这个例子可以运行,就是上传的目录64行的zhangzijie需要指定 # 开始编写上传部分 # import socketserver # import os #使用os模块的join方法 # import json # cod={'1001':'开始上传','1002':'开始续传'} # class Nbserver(socketserver.BaseRequestHandler): # def handle(self): # while 1: # # 1 , 接受命令 # upload_cmd_bytes=self.request.recv(2048) #最大是8k # # upload_cmd_str=json.loads(upload_cmd_bytes).decode("utf8") #错误的写法 # cmd_dic = json.loads(upload_cmd_bytes.decode("utf8")) #是字节有解码的方法《######## # # # # # # 2,获取文件信息 # # file_md5=cmd_dic['md5'] # # file_name=cmd_dic['file_name'] # home=r'E:\老男孩课程\day31\ftp_projrct' # # file_md5_path=os.path.join(home,'zhangzijie',file_md5) # # file_name_path = os.path.join(home, 'zhangzijie', file_name) # upload_file_size=cmd_dic['size'] #所有文件信息都在上面取到的字典里《######## # exist=os.path.exists(file_md5_path) # if not exist: #不续传 # #我没有这个文件,你开始给我传 # #设计状态码 # response = {'code': 1001} # self.request.sendall(json.dumps(response).encode("utf8")) # f=open(file_md5_path,mode='wb') # # recv_size=0 # #接受上传的文件内容 # while recv_size<upload_file_size: # data=self.request.recv(1024) # f.write(data) #写过来的东西都在内存中 # f.flush() #把内存中的东西刷到硬盘中 # recv_size+=len(data) # f.close() # # #改名字, # #os模块的额rename在windows系统中的python2中会报错 # #os.rename(file_md5_path,file_name_path) # #shutil模块在哪都不会报错,除了改文件名还可以该文件夹的名字 # import shutil # shutil.move(file_md5_path,file_name_path) # # else: # #怎么续传呢?你的告诉客户端我已经有多少了,你已经给我传了多少了,对方才能 # #从断开的那里进行继续传 # #根据文件路径获取大小 # exist_szie=os.stat(file_md5_path).st_size # #定义一个协议 # response={'code':1002,'size':exist_szie} # self.request.sendall(json.dumps(response).encode("utf-8")) # self.request.sendall(b'1002') # # f = open(file_md5_path, mode='ab') #这里是追加 # # # recv_size = 0 #这里的总大小就不在是0了,而是已经接受了的大小 # recv_size=exist_szie #这里有个方法,对于后面的变量名,类似的用到了前面的名字 # #可以不用重新再起名字,直接重新赋值把前面的覆盖掉就可以了 # # 接受上传的文件内容 # while recv_size < upload_file_size: # data = self.request.recv(1024) # f.write(data) # 写过来的东西都在内存中 # f.flush() # 把内存中的东西刷到硬盘中 # recv_size += len(data) # f.close() # # # # print(cmd_dic) # # # server=socketserver.ThreadingTCPServer(('127.0.0.1',8001),Nbserver) # server.serve_forever() # ##################################################################################### # 下面这个例子对方法进行归类 # 开始编写上传部分 import socketserver import os #使用os模块的join方法 import json cod={'1001':'开始上传','1002':'开始续传'} def upload(cmd_dic,conn): #用conn代替了下面类中的self.request file_md5 = cmd_dic['md5'] # file_name = cmd_dic['file_name'] home = r'E:\老男孩课程\day31\ftp_projrct' # file_md5_path = os.path.join(home, 'zhangzijie', file_md5) # file_name_path = os.path.join(home, 'zhangzijie', file_name) upload_file_size = cmd_dic['size'] # 所有文件信息都在上面取到的字典里《######## exist = os.path.exists(file_md5_path) if not exist: # 不续传 # 我没有这个文件,你开始给我传 # 设计状态码 response = {'code': 1001} conn.sendall(json.dumps(response).encode("utf8")) f = open(file_md5_path, mode='wb') recv_size = 0 # 接受上传的文件内容 while recv_size < upload_file_size: data = conn.recv(1024) f.write(data) # 写过来的东西都在内存中 f.flush() # 把内存中的东西刷到硬盘中 recv_size += len(data) f.close() # 改名字, # os模块的额rename在windows系统中的python2中会报错 # os.rename(file_md5_path,file_name_path) # shutil模块在哪都不会报错,除了改文件名还可以该文件夹的名字 import shutil shutil.move(file_md5_path, file_name_path) else: # 怎么续传呢?你的告诉客户端我已经有多少了,你已经给我传了多少了,对方才能 # 从断开的那里进行继续传 # 根据文件路径获取大小 exist_szie = os.stat(file_md5_path).st_size # 定义一个协议 response = {'code': 1002, 'size': exist_szie} conn.sendall(json.dumps(response).encode("utf-8")) conn.sendall(b'1002') f = open(file_md5_path, mode='ab') # 这里是追加 # recv_size = 0 #这里的总大小就不在是0了,而是已经接受了的大小 recv_size = exist_szie # 这里有个方法,对于后面的变量名,类似的用到了前面的名字 # 可以不用重新再起名字,直接重新赋值把前面的覆盖掉就可以了 # 接受上传的文件内容 while recv_size < upload_file_size: data = conn.recv(1024) f.write(data) # 写过来的东西都在内存中 f.flush() # 把内存中的东西刷到硬盘中 recv_size += len(data) f.close() class Nbserver(socketserver.BaseRequestHandler): def handle(self): while 1: # 1 , 接受命令 upload_cmd_bytes=self.request.recv(2048) #最大是8k # upload_cmd_str=json.loads(upload_cmd_bytes).decode("utf8") #错误的写法 cmd_dic = json.loads(upload_cmd_bytes.decode("utf8")) #是字节有解码的方法《######## if cmd_dic['cmd']=='upload': upload(cmd_dic,self.request) #函数调用的时候,实参传self.request elif cmd_dic['cmd']=='download': pass #下载的代码 server=socketserver.ThreadingTCPServer(('127.0.0.1',8001),Nbserver) server.serve_forever()
客户端
##以下代码是梳理思路 # import socket # import json # import hashlib # import os # # def file_md5(file_path): # """ # 对文件进行md5加密 # :param file_path: # :return: # """ # obj=open(file_path,mode='rb') # m=hashlib.md5() #实例化MD5 # for line in obj: # m.update(line) #使用md5的update方法 # obj.close() # return m.hexdidest() # # sk=socket.socket() # sk.connect(('127.0.0.1',8001)) # while 1: # cmd=input("请输入命令:") # """ # 1,自定义协议 # {'cmd':'upload','file_path':'.....'} # """ # #获取文件的相关信息 # file_path="/.../" # file_md5_val=file_md5(file_path) # file_name= os.path.basename(file_path) # file_size=os.stat(file_path).st_size # cmd_dict={'cmd':'upload','file_name':file_name,'size':file_size} # # suload_cmd_bytes=json.dumps(cmd_dict).encode("utf8") # sk.sendall(suload_cmd_bytes) # 推荐使用sendall # # #等待服务端的响应 # response=json.loads(sk.recv(8096).decode("utf-8")) #通过序列化与反序列化,最后又转化成字典的操作 # #这种最后就非常方便 # if response['code']==1001: # #从头开始传 # pass # else: # #从断点开始续传 # exist_zise=response['size'] ########################################################################################### # 下面的例子可以运行,就是上传的文件需要指定 # 开始编写上传部分 # import socket # import json # import hashlib # import os # # def file_md5(file_path): # """ # 对文件进行md5加密 # :param file_path: # :return: # """ # obj=open(file_path,mode='rb') # m=hashlib.md5() #实例化MD5 # for line in obj: # m.update(line) #使用md5的update方法 # obj.close() # return m.hexdigest() # # sk=socket.socket() # sk.connect(('127.0.0.1',8001)) # while 1: # cmd=input("请输入命令:") # """ # 1,自定义协议 # {'cmd':'upload','file_path':file_path} # """ # #获取文件的相关信息 # file_path="hello.py" # file_md5_val=file_md5(file_path) # file_name= os.path.basename(file_path) # file_size=os.stat(file_path).st_size # cmd_dict={'cmd':'upload','file_name':file_name,'size':file_size,'md5':file_md5_val} # # suload_cmd_bytes=json.dumps(cmd_dict).encode("utf8") # sk.sendall(suload_cmd_bytes) # 推荐使用sendall # # #等待服务端的响应 # response=json.loads(sk.recv(8096).decode("utf8")) #通过序列化与反序列化,最后又转化成字典的操作 # #这种最后就非常方便 # if response['code']==1001: # #从头开始上传,文件迭代,一行一行发 # # with open(file_path,mode='rb') as f: # # for line in f: # # sk.sendall(line) # #发送可以有两种方式,另外一种如下: # f=open(file_path,mode="rb") # send_size=0 # while send_size< file_size: #不能等于,如果是等于,就会一直循环 # data=f.read(1024) # sk.sendall(data) # send_size+=len(data) # f.close() # # # else: # #从断点开始续传 # exist_zise=response['size'] # f=open(file_path,'rb') # f.seek(exist_zise) #seek跳到某个字节 # send_size=exist_zise #已经发送的等于断点处的字节大小 # while send_size< file_size: #已发的字节小于总大小 # data=f.read(1024) # sk.sendall(data) # send_size+=len(data) # f.close() # ##################################################################################### # 下面的例子对方法进行归类 # 开始编写上传部分 import socket import json import hashlib import os import time #先对函数进行归类 def file_md5(file_path): """ 对文件进行md5加密 :param file_path: :return: """ obj=open(file_path,mode='rb') m=hashlib.md5() #实例化MD5 for line in obj: m.update(line) #使用md5的update方法 obj.close() return m.hexdigest() #进度条 def jdt(size,total_size): val = int(size/total_size * 100) time.sleep(0.1) print('\r%s%%|%s' %(val,"#"*val,), end='') def send_file(exist_zise,file_tocal_size): f = open(file_path, 'rb') f.seek(exist_zise) # seek跳到某个字节 send_size = exist_zise # 已经发送的等于断点处的字节大小 while send_size < file_tocal_size: # 已发的字节小于总大小 data = f.read(1024) sk.sendall(data) send_size += len(data) jdt(send_size,file_tocal_size) #调用进度条函数 f.close() def upload(file_path): #获取文件的相关信息 file_md5_val=file_md5(file_path) file_name= os.path.basename(file_path) file_size=os.stat(file_path).st_size cmd_dict={'cmd':'upload','file_name':file_name,'size':file_size,'md5':file_md5_val} suload_cmd_bytes=json.dumps(cmd_dict).encode("utf8") sk.sendall(suload_cmd_bytes) # 推荐使用sendall #等待服务端的响应 response=json.loads(sk.recv(8096).decode("utf8")) #通过序列化与反序列化,最后又转化成字典的操作 #这种最后就非常方便 if response['code']==1001: #从头开始上传,文件迭代,一行一行发 # with open(file_path,mode='rb') as f: # for line in f: # sk.sendall(line) #发送可以有两种方式,另外一种如下: f=open(file_path,mode="rb") send_file(0,file_size) else: #从断点开始续传 exist_zise=response['size'] send_file(exist_zise,file_size) sk=socket.socket() sk.connect(('127.0.0.1',8001)) while 1: user_onput=input("请输入命令:") cmd,file_path=user_onput.split('|',maxsplit=1) if cmd=='upload': upload(file_path) elif cmd=='download': pass #如果elif特别多可以考虑使用反射