Python Socket实现FTP文件传输与MD5校验完整指南
本文详细介绍如何使用Python Socket库实现简易FTP客户端与服务器,支持文件收发及MD5完整性校验。文章涵盖客户端发送请求、接收文件大小、分块读取数据并计算MD5值,以及服务器端查找文件、发送数据与校验码的完整流程。通过具体代码示例展示连接建立、数据传输及错误处理机制,并指出潜在粘包问题及改进方向,适合Python网络编程初学者参考。
Socket FTP传输原理概述
客户端首先向服务器发送包含文件名的请求,服务器接收到请求后在本地查找对应文件。若文件存在,则启动向客户端发送该文件的流程。
客户端实现详解
1、客户端实现步骤
- 创建Socket连接对象
- 建立与服务器的网络连接
- 用户输入目标文件名
- 将输入的文件名编码后发送给服务器
- 接收服务器返回的待发送文件大小信息
- 向服务器发送确认信息,表示客户端已准备好接收数据
- 开始循环接收文件数据块
- 打印接收完成的提示信息
客户端具体实现的代码如下:
# Author: Mr.Xue
# 2019.10.29
# socket_ftp_client.py
import socket
import hashlib
client = socket.socket() # 生成socket连接对象
client.connect(('localhost', 6961)) # 建立连接
while True:
cmd = input(">>").strip() # 输入想要接收的文件
if len(cmd) == 0: continue # 输入为空,重新再输
if cmd.startswith('get'): # 判断指令是否以get开头
client.send(cmd.encode("utf-8")) # 发送
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() # md5加密
while received_size < file_total_size:
data = client.recv(1024) # 接收数据,一次最大接收1024bytes
received_size += len(data) # 记录已接收的数据大小
m.update(data) # 用md5加密
f.write(data) # 写入文件
else:
new_file_md5 = m.hexdigest() # 16进制显示加密文件
print("file recv done", received_size, file_total_size)
f.close()
server_md5 = client.recv(1024) # 接收服务器端以md5加密的这个接收文件的加密文件,拿来和接收之后的加密文件做比较
print("md5", new_file_md5, server_md5)
client.close()
客户端实现的关键难点在于准确判断服务器发送的数据是否已全部接收完毕,其逻辑已在上述代码中体现,也可参考前文关于Socket通信的第二部分。此外,本次实现新增了一个重要功能:使用MD5算法对接收到的文件进行加密校验。具体做法是先生成MD5实例对象,调用update()方法对文件数据进行加密处理,最后将客户端计算出的MD5值与服务器端发送的MD5值进行比对,以验证文件传输的完整性。
服务器端实现详解
2、服务器实现步骤
- 创建Socket监听对象
- 绑定IP地址与监听端口
- 开启监听模式
- 等待并接受客户端的连接请求
- 接收客户端发送的文件名指令
- 检查本地系统中是否存在该文件
- 若文件存在,打开文件并计算其大小,随后将文件大小发送给客户端
- 等待客户端的确认回复
- 将文件具体内容分块发送给客户端
服务器具体实现代码如下:
# Author: Mr.Xue
# 2019.10.29
# socket_ftp_server.py
import socket, os, hashlib
server = socket.socket() #生成socket对象
server.bind(('localhost', 6961)) # 绑定ip和端口
server.listen() #监听
while True:
conn, addr = server.accept() # 等待客户端连接
while True:
print("等待接收文件名...")
data = conn.recv(1024) # 接收客户端发来的信息
if not data: #判断客户端是否断连
print('lost a link...')
break
cmd, filename = data.decode().split() # 分割接收到的消息,提取出文件名
if os.path.isfile(filename): # 判断文件是否存在
f = open(filename, 'rb') # 打开文件
m = hashlib.md5() # md5加密对象
file_size = os.stat(filename).st_size # 计算文件大小
conn.send(str(file_size).encode("utf-8")) # send file size
conn.recv(1024) # wait the ack 预防粘包
for line in f:
m.update(line) # 加密
conn.send(line) # 发送
print("file md5:", m.hexdigest()) # 以16进制打印加密后的文件
f.close() # 关闭文件
conn.send(m.hexdigest().encode("utf-8")) # 以16进制发送加密后的文件
print('send done')
socket.close()
服务器的核心逻辑与前文所述基本一致,主要区别在于增加了文件查找、读取以及MD5加密计算的具体处理细节。
测试效果与问题分析
3、测试效果演示
启动服务器进程
xue@xue-MacBookAir:~/python_learn$ python3 socket_ftp_server.py
启动客户端进程
client
xue@xue-MacBookAir:~/python_learn$ python3 socket_ftp_client.py >>
server
xue@xue-MacBookAir:~/python_learn$ python3 socket_ftp_server.py 等待接收文件名...
客户端发送想要接收的文件名
client
xue@xue-MacBookAir:~/python_learn$ python3 socket_ftp_client.py >>get a.txt server response: b'90' file recv done 90 90 md5 2232897a127542c1d0715e66e7ca57cc b'2232897a127542c1d0715e66e7ca57cc' >>
server
xue@xue-MacBookAir:~/python_learn$ python3 socket_ftp_server.py 等待接收文件名... file md5: 2232897a127542c1d0715e66e7ca57cc send done 等待接收文件名...
上述服务器端在发送完文件数据后,紧接着发送了MD5加密后的文件哈希值。这种连续发送可能导致网络通信中的粘包现象。因此,当前实现仍有优化空间,若加入预防粘包的代码逻辑,整体流程将更加完善。
总结
至此,关于使用Python Socket实现FTP客户端与服务器之间文件收发及MD5加密校验的教程已介绍完毕。如需了解更多关于Python Socket实现FTP收发文件及MD5加密的内容,请搜索本站历史文章或继续浏览后续相关教程。感谢大家的支持!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









