FTP(File Transfer Protocol,文件传输协议) 是 TCP/IP 协议组中的协议之一。FTP 协议包括两个组成部分,其一为 FTP 服务器,其二为 FTP 客户端。其中 FTP 服务器用来存储文件,用户可以使用 FTP 客户端通过 FTP 协议访问位于 FTP 服务器上的资源。在开发网站的时候,通常利用 FTP 协议把网页或程序传到 Web 服务器上。此外,由于 FTP 传输效率非常高,在网络上传输大的文件时,一般也采用该协议。
默认情况下 FTP 协议使用 TCP 端口中的 20 和 21 这两个端口,其中 20 用于传输数据,21 用于传输控制信息。但是,是否使用 20 作为传输数据的端口与 FTP 使用的传输模式有关,如果采用主动模式,那么数据传输端口就是 20;如果采用被动模式,则具体最终使用哪个端口要服务器端和客户端协商决定。
我们使用第三方实现的 FTP 协议 pyftpdlib 模块来编写 FTP
服务器端程序,首先,大家先把该模块安装上,安装命令:pip install
-i https://pypi.tuna.tsinghua.edu.cn/simple pyftpdlib
,服务器端代码如下。
from pyftpdlib.authorizers import DummyAuthorizer from pyftpdlib.handlers import FTPHandler, ThrottledDTPHandler from pyftpdlib.servers import FTPServer from pyftpdlib.log import LogFormatter import logging # 记录日志,默认情况下日志仅输出到屏幕(终端),这里既输出到屏幕又输出到文件,方便日志查看 logger = logging.getLogger() logger.setLevel(logging.INFO) ch = logging.StreamHandler() fh = logging.FileHandler(filename='myftpserver.log', encoding='utf-8') # 日志文件 ch.setFormatter(LogFormatter()) fh.setFormatter(LogFormatter()) logger.addHandler(ch) # 将日志输出至屏幕 logger.addHandler(fh) # 将日志输出至文件 # 实例化虚拟用户,这是 FTP 验证首要条件 authorizer = DummyAuthorizer() ''' 添加用户权限和路径,括号内的参数是(用户名、密码、用户目录、权限),可以为不同的用户添加不同的目录和权限 读权限: e: 改变文件目录;l: 列出文件; r: 从服务器接收文件 写权限: a: 文件上传; d: 删除文件; f: 文件重命名; m: 创建文件; w: 写权限; M: 文件传输模式(通过FTP设置文件权限) ''' authorizer.add_user("user", "123456", r"ftp", perm="elradfmw") # 添加匿名用户,只需要路径 authorizer.add_anonymous(r"ftp") # 初始化ftp句柄 handler = FTPHandler handler.authorizer = authorizer # 添加被动端口范围 handler.passive_ports = range(2000, 2333) # 下载上传速度设置 dtp_handler = ThrottledDTPHandler dtp_handler.read_limit = 300 * 1024 # 300kb/s dtp_handler.write_limit = 300 * 1024 # 300kb/s handler.dtp_handler = dtp_handler # 监听 IP 和端口,我们使用 21 端口 server = FTPServer(("0.0.0.0", 21), handler) # 最大连接数 server.max_cons = 150 server.max_cons_per_ip = 15 # 开始服务,自带日志打印信息 server.serve_forever()
服务器端工程目录结构如下图,首先在和服务器端程序同目录下有个日志文件:myftpserver.log
该文件记录服务器和客户端通信的日志。然后,工程目录下有个文件夹 ftp,该文件夹下有个 test 文件夹,test 文件夹下存放服务器端的文件,客户端可以从这里下载文件,同样客户端上传的文件也都放在这里。
FTP 服务端搭建好后,先启动服务器端程序,然后启动客户端程序,客户端就可以和服务器进行文件传输了,我们可以从服务器端下载文件,也可以把客户端本地文件上传到服务器。在此我们使用 python 自带的 ftplib 模块,该模块也实现了 FTP 协议,客户端代码如下。
from ftplib import FTP # 登录FTP ftp = FTP(host='127.0.0.1', user='user', passwd='123456') # 设置编码方式 ftp.encoding = 'utf-8' # 切换目录 ftp.cwd('test') # 列出文件夹的内容 ftp.retrlines('LIST') # ftp.dir() # 从服务器端下载 node.txt ftp.retrbinary('RETR node.txt', open('node.txt', 'wb').write) # 上传本地文件 ftp.storbinary('STOR bird.png', open('bird.png', 'rb')) # 查看目录下的文件详情 for f in ftp.mlsd(path='/test'): print(f)
客户端工程目录如下图,和客户端程序同目录下有个 bird.png 文件,我们的客户端的功能是从服务器上下载文件 node.txt 到本地工程目录下,然后把 bird.png 文件上传到服务器端。
我们上面的服务器端使用的第三方模块 pyftpdlib,客户端使用的内置模块 ftplib,这两个模块实现了 FTP 协议,当然,同学们也可以在服务器端使用 ftplib 模块。
我们知道文件传输是不允许丢包的,因为哪怕丢了一个字符都是非常危险的事情,比如三胖和老特商量要不要开打, 三胖给老特发了一个文件,文件内容是:“老特,我们不打”,结果文件内容中的“不”字在网络上传输时丢失了,就会造成灾难性后果。我们知道 TCP 协议就已经做到完整性和可靠性了,所以文件传输协议(FTP)是基于 TCP 协议的应用层协议。
当然,你也可以自己用 TCP 协议来实现文件传输,这样的话,我们就需要自己编写 FTP 协议,编写 FTP 协议,自己编写基于 TCP 协议的应用层协议,一定要注意做粘包分包处理。同学们可以作为一个作业来自己实现文件传输。
会使用第三方模块 pyftpdlib 和 python 内置模块 ftplib。
跑通上面的服务器和客户端程序,实现文件上传和下载。
查找资料了解 FTP 协议的概念和知识点。
基于 TCP 协议,编写一个简单的 FTP 服务器和客户端。注意,要自己构建应用层协议,自己做粘包分包处理。
这个教程,我感觉比我平时百度学习好多了[大笑]