python学习之路(三)使用socketserver进行ftp断点续传
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了python学习之路(三)使用socketserver进行ftp断点续传,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含5603字,纯文字阅读大概需要9分钟。
内容图文
最近学习python到socketserver,本着想试一下水的深浅,采用Python3.6.
目录结构如下:
receive_file和file为下载或上传文件存放目录,ftp_client为ftp客户端,ftp_server为server端。
server端源码:
# !/usr/bin/env python # -*- coding:utf-8 -*- import socketserver import os error_code = {‘400‘:‘FILE IS NOT EXISTS‘} file_path = os.path.join(os.path.abspath(‘.‘),‘file‘) #获取文件目录路径‘‘‘服务端采用socketserver方式‘‘‘class MyTCPHandler(socketserver.BaseRequestHandler): def handle(self): while True: # print(‘new conn‘,self.client_address) data = self.request.recv(100) #接收客户端请求ifnot data.decode(): breakelif data.decode().split()[0] == ‘get‘: #server判断是下载还是上传文件,get是下载 offset = data.decode().split(‘|‘)[1] #取出偏移量 file = data.decode().split()[1].split(‘|‘)[0] #取出要下载的文件名 filename = os.path.join(file_path,file) read_len = 0 if os.path.exists(filename) : #判断是否有资源 with open(filename,‘rb‘) as fd: while True: send_data = fd.read(1024) read_len += len(send_data) #记录读取数据长度if send_data and read_len > int(offset): #达到偏移量发送数据 ack_msg = "SEND SIZE|%s" % len(send_data) self.request.send(ack_msg.encode()) client_ack = self.request.recv(50) if client_ack.decode() =="CLIENT_READY_TO_RECV": self.request.send(send_data) elif read_len <= int(offset): continueelse: send_data =‘END‘ self.request.send(send_data.encode()) #数据传输完毕发送finally信号breakelse: msg = ‘400‘ self.request.send(msg.encode()) elif data.decode().split()[0] == ‘put‘: #判断客户端是不是上传行为 file = data.decode().split()[1] #获取需要上传的文件名 filename = os.path.join(file_path,file) #定义文件路径 log = "%s.%s" % (file,‘log‘) #指定记录偏移日志文件名 logname = os.path.join(file_path,log) #定义日志路径if os.path.exists(filename) and os.path.exists(logname): #如果要上传的文件和日志文件同时存在,说明需要进行续传 with open(logname) as f: offset = f.read().strip() #读取偏移量else: offset = 0 #表示不需要进行续传,直接从头开始传 server_syn_msg = "offset %s" % offset #把偏移信息发送给客户端 self.request.send(server_syn_msg.encode()) total_len = int(offset) #获取已传输完的文件长度,即从这个位置开始接收新的数据while True: receive_ack = self.request.recv(100) #客户端接收到偏移信息后通知服务端要发送数据的长度信息,相当于一个ack res_msg = receive_ack.decode().split(‘|‘) if receive_ack.decode() == ‘END‘: #判断文件是否上传完成,完成后删掉偏移日志 os.remove(logname) breakelif res_msg[0].strip() ==‘SEND SIZE‘: #如果服务端收到了客户端发送过来的ack,给客户端返回一个syn信息,表示可以开始传数据了 res_size = res_msg[1] self.request.send(b‘CLIENT_READY_TO_RECV‘) recv_data = self.request.recv(1024) #接收数据 total_len += len(recv_data) #记录接收数据长度 with open(filename,‘ab‘) as fd: #以追加的方式写入文件 fd.write(recv_data) with open(logname,‘w‘) as f: #把已接收到的数据长度写入日志 f.write(str(total_len)) if__name__ == ‘__main__‘: host,port = "localhost",5000 server = socketserver.ThreadingTCPServer((host,port),MyTCPHandler) server.serve_forever() #开启服务端
客户端源码:
# !/usr/bin/env python # -*- coding:utf-8 -*- import socket import os,sys receive_file_path = os.path.abspath(os.path.join(os.path.abspath(‘.‘),‘receive_file‘)) #指定文件目录路径 error_code = {‘400‘:‘FILE IS NOT EXISTS‘} ‘‘‘使用类的方式,方便反射‘‘‘class SOCKET(object): def__init__(self,ip,port): self.ip = ip self.port = port def socket_obj(self): sk = socket.socket() sk.connect((self.ip,self.port)) return sk def get(self): #get表示从服务端下载文件到本地 conn = self.socket_obj() #生成对象 user_input = input(‘get filename:‘) #指定输入命令格式 get filename# print(msg,type(msg)) filename = user_input.split()[1] #获取文件名 file = os.path.join(receive_file_path,filename) #下载文件的绝对路径 logname = ‘%s.%s‘ % (filename,‘log‘) #生成日志名 log = os.path.join(receive_file_path,logname) #偏移量日志的绝对路径if os.path.exists(log) and os.path.exists(file): #判断是否需要续传,如果需要就读出偏移量 with open(log) as f: offset = f.read().strip() else: offset = 0 # 否则偏移量置0 msg = "%s|%s" %(user_input,offset) conn.send(msg.encode()) total_length = int(offset) #记录传输完成了多少while True: server_ack_msg = conn.recv(100) #接收第一个ackif server_ack_msg.decode().strip() == ‘400‘: #如果ftp服务器没有这个资源,返回错误print(‘400‘, error_code[‘400‘]) conn.close() breakelif server_ack_msg.decode().strip() == ‘END‘: #传输完成,ftp server返回字段,并删除偏移量日志 conn.close() os.remove(log) break res_msg = server_ack_msg.decode().split(‘|‘) #接收server的syn和传输数据大小的信息if res_msg[0].strip() == "SEND SIZE": res_size = int(res_msg[1]) conn.send(b‘CLIENT_READY_TO_RECV‘) #给server返回ack receive_data = conn.recv(1024) #接收server的数据 total_length += len(receive_data) #记录接收到了多少数据# print(receive_data.decode())# print(total_length) with open(file,‘ab‘) as fd: #以追加的方式写文件 fd.write(receive_data) with open(log,‘w‘) as f: #把已接收数据长度写进日志 f.write(str(total_length)) def put(self): #put表示上传文件至服务端 conn = self.socket_obj() #生成对象 msg = input(‘put filename:‘) #指定命令输入格式,put filename filename = os.path.join(receive_file_path, msg.split()[1]) #生成上传文件路径if os.path.exists(filename): #判断文件存在与否,不存在返回错误 conn.send(msg.encode()) #发送文件行为与文件名至服务端 server_syn_msg = conn.recv(100) #接收服务端发送的偏移量信息 offset = server_syn_msg.decode().split()[1] read_length = 0 #重置需要读取文件的长度 with open(filename,‘rb‘) as fd: while True: send_data = fd.read(1024) #开始读取文件,每次读取1024字节 read_length += len(send_data) #记录读取数据长度if send_data and read_length> int(offset): #和服务端发送的偏移量进行比较,只有数据不为空和读到超过偏移量才会发送数据 ack_msg = "SEND SIZE|%s" %len(send_data) #给服务端发送本次要发送数据的长度,相当于一个syn conn.send(ack_msg.encode()) client_ack = conn.recv(100) #接收到服务端发送的ack确认信息,收到之后开始传输数据if client_ack.decode() ==‘CLIENT_READY_TO_RECV‘: conn.send(send_data) elif read_length <= int(offset): #如果读取到的数据长度没到偏移量就继续循环读取文件continueelse: send_data = ‘END‘#文件已经读完,表示已经全部发送完成,给服务端发送信息说明客户端已经发送完成 conn.send(send_data.encode()) breakelse: print(‘400‘, error_code[‘400‘]) if__name__ == ‘__main__‘: c = SOCKET(‘127.0.0.1‘,5000) if hasattr(c,sys.argv[1]): func = getattr(c,sys.argv[1]) func()
由于时间原因,存在在传输的过程中有些文件里面涉及到中文的可能会报错的bug,只是功能基本实现,给大家分享一下我的思路,方便交流
原文:http://www.cnblogs.com/wrlinux/p/7051257.html
内容总结
以上是互联网集市为您收集整理的python学习之路(三)使用socketserver进行ftp断点续传全部内容,希望文章能够帮你解决python学习之路(三)使用socketserver进行ftp断点续传所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。