python实现ftp文件传输功能


Posted in Python onMarch 20, 2020

本文实例为大家分享了python实现ftp文件传输的具体代码,供大家参考,具体内容如下

主要步骤可以分为以下几步:

1.读取文件名
2.检测文件是否存在
3.打开文件
4.检测文件大小
5.发送文件大小和 md5值给客户端
6.等客户端确认
7.开始边读边发数据

服务器端代码:

import socket,os,time
import hashlib
 
server =socket.socket()
server.bind(('0.0.0.0',6666))
server.listen()
print("等待....")
while True:
 conn,addr = server.accept()
 print("new conn:",conn)
 while True:
 data = conn.recv(1024)
 if not data:
 print("client is disconnection")
 break
 cmd,filename = data.decode().split() #记录指令和文件名
 print(filename)
 #判断当前目录是否存在该文件,而且必须是文件,而不是目录
 if os.path.isfile(filename):
 f = open(filename,'rb')
 #m = hashlib.md5() # 创建md5
 file_size = os.stat(filename).st_size #stat() 可以返回文件的大小值
 conn.send((str(file_size)).encode()) # 发送文件大小
 conn.recv(1024) #等待返回信息
 for line in f:
 # m.updata(line) 
 conn.send(line)
 #print("file md5",m.hexdigest()) #打印md5值
 f.close()

客户端代码:

# Author: zjt
import socket
 
client = socket.socket()
 
client.connect(("0.0.0.0",6666))
 
 
while True:
 cmd = input(">>>:").strip()
 
 if len(cmd)==0 :continue
 
 if cmd.startswith("get"):
 client.send(cmd.encode())
 server_response = client.recv(1024)
 print("server response: ",server_response)
 client.send(b"ready to recv file")
 
 # 开始接收文件
 file_total_size = int(server_response.decode())
 received_size = 0 # 记录接收文件的大小
 filename = cmd.split()[1]
 # 因为两个目录一致,接收的文件名不能与原文件相同
 f = open(filename+".new","wb")
 while received_size < file_total_size:
 data = client.recv(1024)
 received_size += len(data)
 f.write(data)
 print("total:",file_total_size," present: ",received_size)
 else:
 print("file has received done!")
 f.close()
 
client.close()

用80M的文件传输测试,效果如下:

python实现ftp文件传输功能

程序升级:

前面的代码还没添加md5进行验证,现在对代码进行升级

服务器端代码:

import socket,os,time
import hashlib
 
server =socket.socket()
server.bind(('0.0.0.0',8888))
server.listen()
print("等待....")
while True:
 conn,addr = server.accept()
 print("new conn:",conn)
 while True:
 data = conn.recv(1024)
 if not data:
 print("client is disconnection")
 break
 cmd,filename = data.decode().split() #记录指令和文件名
 print(filename)
 #判断当前目录是否存在该文件,而且必须是文件,而不是目录
 if os.path.isfile(filename):
 f = open(filename,'rb')
 m = hashlib.md5() # 创建md5
 file_size = os.stat(filename).st_size #stat() 可以返回文件的大小值
 conn.send((str(file_size)).encode()) # 发送文件大小
 conn.recv(1024) #等待返回信息
 for line in f:
 m.update(line)
 conn.send(line)
 print("file md5",m.hexdigest()) #打印md5值
 
 f.close()
 conn.send(m.hexdigest().encode()) # 发送md5
 
 print("我真的已经发过去了",m.hexdigest().encode())
 
 print("send done")
 
server.close()

客户端代码:

import socket
import hashlib
client = socket.socket()
client.connect(("0.0.0.0",8888))
while True:
 cmd = input(">>>:").strip()
 if len(cmd)==0 :continue
 if cmd.startswith("get"):
 client.send(cmd.encode())
 server_response = client.recv(1024)
 print("server response: ",server_response)
 client.send(b"ready to recv file")
 # 开始接收文件
 file_total_size = int(server_response.decode())
 received_size = 0 # 记录接收文件的大小
 filename = cmd.split()[1]
 # 因为两个目录一致,接收的文件名不能与原文件相同
 f = open(filename+".new","wb")
 m = hashlib.md5()
 while received_size < file_total_size:
 data = client.recv(1024)
 received_size += len(data)
 m.update(data)
 f.write(data)
 #print("total:",file_total_size," present: ",received_size)
 else:
 new_file_md5 = m.hexdigest()
 print("client file md5:",new_file_md5)
 print("file has received done!")
 print("total:",file_total_size," present: ",received_size)
 f.close()
 sever_file_md5 = client.recv(1024)
 print("client file md5:",new_file_md5)
 print("server file md5:",sever_file_md5)
client.close()

两个程序在linux 环境下运行,结果如下:

python实现ftp文件传输功能

可以看到传输后文件大小变大了一点点,而且md5前后值也不同,说明文件传输发生了改变。

现在讲程序在windows环境下运行,结果如下:

python实现ftp文件传输功能

此时可以看到windows上没有问题,文件大小相同,且md5值也一致。

原因分析:

之所以会发生这种情况,是因为在linux上运行时,最后一次传输文件与发送md5值的时候,发生可粘包,导致最后一次接收文件的时候,连同md5的数据一并发送了。而客户端也当作一条接收信息,全部接收了。所以客户端出现没有收到来自服务器端的md5值,多出来的那一点点,就是md5值的大小。

解决方法:

在接收文件的时候,判断当前剩余多少文件需要接收,如果大于1024,就接收1024大小的文件,否则就只接收剩下全部的文件,防止最后一次接收多余的数据。

只需要对客户端代码进行修改,修改后代码如下:

import socket
import hashlib
client = socket.socket()
client.connect(("0.0.0.0",8888))
while True:
 cmd = input(">>>:").strip()
 if len(cmd)==0 :continue
 if cmd.startswith("get"):
 client.send(cmd.encode())
 server_response = client.recv(1024)
 print("server response: ",server_response)
 client.send(b"ready to recv file")
 # 开始接收文件
 file_total_size = int(server_response.decode())
 received_size = 0 # 记录接收文件的大小
 filename = cmd.split()[1]
 f = open(filename+".new","wb")
 m = hashlib.md5()
 while received_size < file_total_size:
 #添加一次判断,使最后一次剩多少就接收多少,避免发生粘包
 if file_total_size - received_size > 1024:
  size = 1024
 else: # 最后一次,剩多少收多少
  size = file_total_size - received_size
 data = client.recv(size)
 received_size += len(data)
 m.update(data)
 f.write(data)
 else:
 new_file_md5 = m.hexdigest() 
 print("client file md5:",new_file_md5)
 print("file has received done!")
 print("total:",file_total_size," present: ",received_size)
 print("下一句关闭文件")
 f.close()
 print("开始接收md5 ") 
 sever_file_md5 = client.recv(1024)
 print("client file md5:",new_file_md5)
 print("server file md5:",sever_file_md5)
client.close()

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
用Python编写一个简单的FUSE文件系统的教程
Apr 02 Python
简介Python中用于处理字符串的center()方法
May 18 Python
在Python程序中操作文件之flush()方法的使用教程
May 24 Python
解决python 输出是省略号的问题
Apr 19 Python
Scrapy基于selenium结合爬取淘宝的实例讲解
Jun 13 Python
python实现俄罗斯方块游戏(改进版)
Mar 13 Python
如何理解python面向对象编程
Jun 01 Python
Matplotlib自定义坐标轴刻度的实现示例
Jun 18 Python
Python自动发送和收取邮件的方法
Aug 12 Python
python+django+selenium搭建简易自动化测试
Aug 19 Python
pytorch中index_select()的用法详解
Jan 06 Python
用gpu训练好的神经网络,用tensorflow-cpu跑出错的原因及解决方案
Mar 03 Python
Python开发之身份证验证库id_validator验证身份证号合法性及根据身份证号返回住址年龄等信息
Mar 20 #Python
python实现FTP文件传输的方法(服务器端和客户端)
Mar 20 #Python
python实现ftp文件传输系统(案例分析)
Mar 20 #Python
关于Python 中的时间处理包datetime和arrow的方法详解
Mar 19 #Python
JetBrains PyCharm(Community版本)的下载、安装和初步使用图文教程详解
Mar 19 #Python
Python文件操作基础流程解析
Mar 19 #Python
Python函数基本使用原理详解
Mar 19 #Python
You might like
用PHP实现读取和编写XML DOM代码
2010/04/07 PHP
百度ping方法使用示例 自动ping百度
2014/01/26 PHP
php实现通过ftp上传文件
2015/06/19 PHP
基于ThinkPHP+uploadify+upload+PHPExcel 无刷新导入数据
2015/09/23 PHP
php上传大文件失败的原因及应对策略
2015/10/20 PHP
网页自动刷新,不产生嗒嗒声的一个解决方法
2007/03/27 Javascript
javascript之querySelector和querySelectorAll使用介绍
2011/12/20 Javascript
jquery动态加载select下拉框示例代码
2013/12/10 Javascript
详解JavaScript中getFullYear()方法的使用
2015/06/10 Javascript
JavaScript多线程详解
2015/08/12 Javascript
AngularJS基础 ng-click 指令示例代码
2016/08/01 Javascript
webpack实践之DLLPlugin 和 DLLReferencePlugin的使用教程
2019/06/10 Javascript
vue 实现单选框设置默认选中值
2019/11/07 Javascript
js实现带积分弹球小游戏
2020/07/21 Javascript
Vue中使用JsonView来展示Json树的实例代码
2020/11/16 Javascript
JS常用跨域方法实现原理解析
2020/12/09 Javascript
[01:47]2018年度DOTA2最具人气解说-完美盛典
2018/12/16 DOTA
python实现探测socket和web服务示例
2014/03/28 Python
python 把数据 json格式输出的实例代码
2016/10/31 Python
python实现的正则表达式功能入门教程【经典】
2017/06/05 Python
在PyCharm中三步完成PyPy解释器的配置的方法
2018/10/29 Python
Python 限定函数参数的类型及默认值方式
2019/12/24 Python
windows下Pycharm安装opencv的多种方法
2020/03/05 Python
python如何绘制疫情图
2020/09/16 Python
HomeAway澳大利亚:预订你的度假屋,公寓、度假村、别墅等
2019/02/20 全球购物
伦敦著名的运动鞋综合商店:Footpatrol
2019/03/25 全球购物
Easy Spirit官网:美国休闲鞋履中的代表品牌
2019/04/12 全球购物
什么叫应用程序域?什么是托管代码?什么是强类型系统?什么是装箱和拆箱?什么是重载?CTS、CLS和CLR分别作何解释?
2012/05/23 面试题
用C#语言写出与SQLSERVER访问时的具体过程
2013/04/16 面试题
《放小鸟》教学反思
2014/04/20 职场文书
实践单位评语
2014/04/26 职场文书
主题教育活动总结
2014/05/05 职场文书
学党史心得体会
2014/09/05 职场文书
会计师事务所实习证明
2014/11/16 职场文书
2014年医药代表工作总结
2014/11/22 职场文书
Python基本数据类型之字符串str
2021/07/21 Python