FTP 需要 pyftpdlib 包的支持。
https://pypi.org/project/pyftpdlib/
https://github.com/giampaolo/pyftpdlib/
根据文档,使用统一套代码支持 Python 2.6 - 3.5。我在更高的 Python 版本上运行也挺正常的。
根据文档上的性能测试数据,它的传输速度和 Linux 上常用的两款 FTP 服务器 vsftpd 和 proftpd 相同,但是有更好的并发性能(远超)。
python3 -m pip install pyftpdlib --user
# 默认工作在 0.0.0.0:2121 端口, 只读, 匿名登录
python3 -m pyftpdlib -d ~/Documents/Mine/
python3 -m pyftpdlib -d ~/Documents/Mine/ -p 21
python3 -m pyftpdlib -d ~/Documents/Mine/ -w
python3 -m pyftpdlib -d ~/Documents/Mine/ -u sharefile -P markjour.com
# -h, --help
# -i ADDRESS, --interface=ADDRESS
# -p PORT, --port=PORT
# -w, --write
# grants write access for logged in user (default read-only)
# -d FOLDER, --directory=FOLDER
# -n ADDRESS, --nat-address=ADDRESS
# the NAT address to use for passive connections
# -r FROM-TO, --range=FROM-TO
# the range of TCP ports to use for passive connections (e.g. -r 8000-9000)
# -D, --debug
# -v, --version
# -V, --verbose
# -u USERNAME, --username=USERNAME
# -P PASSWORD, --password=PASSWORD
TFTP Server
Trivial File Transfer Protocol
协议极其简单,只支持文件传输,常用于 PXE 网络引导。
两个知名协议:BOOTP 和 DHCP 的网络引导部分都包含 TFTP 协议相关内容。
- RFC 783, The TFTP Protocol (Revision 1), 1981
- RFC 1350, The TFTP Protocol (Revision 2), 1992
其他只需要提供简单文件传输的场景也可以使用 TFTP。
TFTP 和 FTP 之间没有继承关系,他们之间的主要差别:
- TFTP 是 UDP 协议,FTP 是 TCP 协议。
- TFTP 服务只需要建立一个连接(服务器 69 端口),而 FTP 使用两个连接:
- 控制连接,服务器 21 端口
- 数据连接,服务器随机端口
- TFTP 非常简单,支持的命令较少,比如:
- 不支持认证
- 不支持列出目录内容
- 不支持主动模式(FTP 上用的很少的功能)
遗憾的是,tftpy 和 fbtftp 两个包都不支持直接运行。
# python3 -m pip install tftpy --user
python3 -m pip install fbtftp --user
参照官方文档,可以这样运行:
import os
from fbtftp.base_handler import BaseHandler, ResponseData
from fbtftp.base_server import BaseServer
class FileResponseData(ResponseData):
def __init__(self, path):
self._size = os.stat(path).st_size
self._reader = open(path, 'rb')
def read(self, n):
return self._reader.read(n)
def size(self):
return self._size
def close(self):
self._reader.close()
def print_session_stats(stats):
print(stats)
def print_server_stats(stats):
counters = stats.get_and_reset_all_counters()
print('Server stats - every {} seconds'.format(stats.interval))
print(counters)
class StaticHandler(BaseHandler):
def __init__(self, server_addr, peer, path, options, root, stats_callback):
self._root = root
super().__init__(server_addr, peer, path, options, stats_callback)
def get_response_data(self):
return FileResponseData(os.path.join(self._root, self._path))
class StaticServer(BaseServer):
def __init__(self, address, port, retries, timeout, root,
handler_stats_callback, server_stats_callback=None):
self._root = root
self._handler_stats_callback = handler_stats_callback
super().__init__(address, port, retries, timeout, server_stats_callback)
def get_handler(self, server_addr, peer, path, options):
return StaticHandler(server_addr, peer, path, options, self._root,
self._handler_stats_callback)
def main():
server = StaticServer(address='::', port=69, retries=3, timeout=5,
root='/var/tftproot',
handler_stats_callback=print_session_stats,
server_stats_callback=print_server_stats)
try:
server.run()
except KeyboardInterrupt:
server.close()
if __name__ == '__main__':
main()
SFTP
有两种含义:
- Simple File Transfer Protocol, RFC913, 实际没有使用过
- SSH File Transfer Protocol, 或者 Secure File Transfer Protocol
工作在 SSH 之上,比 SCP 提供更高多的文件管理操作。
绝大部分时候,提到 SFTP 都是指第二种。
虽然 SFTP 不复杂,但是需要实现 SSH 协议,能找到一些 Python 项目提供支持,但是由于一般的 SSH 服务器都提供 SFTP 功能,所以应该没有什么场景会使用到这些 Python 库。