使用 python 快速建立 FTP 服务器和客户端

摘要:本文的文字及图片来源于网络,仅供学习、交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理
本文章来自腾讯云 作者:somenzz
**想要学习Python?有问题得不到第一时间解决?来看看这里“1039649593”满足你的需求,资料都已经上传至文件中,可以自行下载!还有海量最新2020python学习资料。[点击查看](https://jq.qq.com/?_wv

使用 python 快速建立 FTP 服务器和客户端

本文的文字及图片来源于网络,仅供学习、交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理
本文章来自腾讯云 作者:somenzz
想要学习Python?有问题得不到第一时间解决?来看看这里“1039649593”满足你的需求,资料都已经上传至文件中,可以自行下载!还有海量最新2020python学习资料。点击查看

使用 python 快速建立 FTP 服务器和客户端
在运维工作中我们可能经常需要共享或传输文件,最简单快捷的方法就是搭建一个FTP服务器。那么我们有必要先了解一下什么是ftp。
FTP 就是 File Transfer Protocol(文件传输协议) 它运行在TCP协议之上,使用两个端口:一个是数据端口,一个是命令端口,也称控制端口。默认情况下20是数据端口,21是命令端口。FTP有两种传输模式:
主动模式:
主动模式下,客户端从任意的非特殊端口n(大于1023的端口)连接FTP服务器的命令端口(默认是21),然后在n+1端口监听。用图表示如下:
在第1步中,客户端的命令端口与FTP服务器的命令端口建立连接,并发送命令“PORT 1027”。然后在第2步中,FTP服务器给客户端的命令端口返回一个”ACK”。在第3步中,FTP服务器发起一个从它自己的数据端口(20)到客户端先前指定的数据端口(1027)的连接,最后客户端在第4步中给服务器端返回一个”ACK”。主动模式如下图所示。

主动方式FTP的主要问题实际上在于客户端。FTP的客户端并没有实际建立一个到服务器数据端口的连接,它只是简单的告诉服务器自己监听的端口号,服务器再回来连接客户端这个指定的端口。对于客户端的防火墙来说,这是从外部系统建立到内部客户端的连接,这是通常会被阻塞的。
被动模式:
为了解决服务器发起到客户的连接的问题,人们开发了被动方式,或者叫做PASV,当客户端通知服务器它处于被动模式时才启用。在被动方式FTP中,命令连接和数据连接都由客户端发起。当开启一个FTP连接时,客户端打开两个任意的非特权本地端口(大于 1023)。第一个端口连接服务器的21端口,但与主动方式的FTP不同,客户端不会提交PORT命令并允许服务器来回连它的数据端口,而是提交PASV命令。这样做的结果是服务器会开启一个任意的非特权端口,并发送PORT P命令给客户端。然后客户端发起从本地端口N+1到服务器的端口P的连接用来传送数据。
用图表示如下所示:

简单总结

主动FTP对FTP服务器的管理有利,但对客户端的管理不利。因为FTP服务器企图与客户端的高位随机端口建立连接,而这个端口很有可能被客户端的防火墙阻塞掉。被动FTP对FTP客户端的管理有利,但对服务器端的管理不利。因为客户端要与服务器端建立两个连接,其中一个连到一个高位随机端口,而这个端口很有可能被服务器端的防火墙阻塞掉。
简单了解了FTP之后接下来我们首先使用Python搭建一个FTP 服务器
搭建 FTP 服务器
安装 pyftpdlig

1
pip install pyftpdlib

使用pyftpdlib搭建一个服务器 myftpserver1.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
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')
ch.setFormatter(LogFormatter())
fh.setFormatter(LogFormatter())
logger.addHandler(ch) #将日志输出至屏幕
logger.addHandler(fh) #将日志输出至文件

# 实例化虚拟用户,这是FTP验证首要条件
authorizer = DummyAuthorizer()
# 添加用户权限和路径,括号内的参数是(用户名, 密码, 用户目录, 权限),可以为不同的用户添加不同的目录和权限
authorizer.add_user("user", "12345", "d:/", perm="elradfmw")
# 添加匿名用户 只需要路径
authorizer.add_anonymous("d:/")
你好
# 初始化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

# 监听ip 和 端口,linux里需要root用户才能使用21端口
server = FTPServer(("0.0.0.0", 21), handler)

# 最大连接数
server.max_cons = 150
server.max_cons_per_ip = 15

# 开始服务,自带日志打印信息
server.serve_forever()

执行 python myftpserver1.py 运行结果如下图所示

在程序目录下会看到生成了myftpserver.log,文件内容与终端打印内容一致。
现在我们在命令窗口进行登陆测试

服务器窗口如下所示


注意
在winddows系统中可能会有乱码,原因是pyftpdlib内部使用utf8,而windows使用gbk,解决方法如下:
修改pyftpdlib包中的filesystems.py,找到

1
yield line.encode('utf8', self.cmd_channel.unicode_errors)

共有两处,将此处的utf8改为gbk,
修改pyftpdlib包中的handlers.py,找到FTPHandler的decode方法

1
return bytes.decode('utf8', self.unicode_errors)

将此处的utf8改为gbk即可解决乱码问题。
更快的操作
如果我们只想在当前目录建立一个ftp服务器供别人下载文件,那么在当前路径直接执行

1
python -n pyftpdlib -p 21 

可以看到有如下结果

那么问题来了,如何使用python操作 FTP 服务器上的文件呢?
编写 FTP 客户端程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#-*- encoding:utf-8 -*-
from ftplib import FTP
#登陆FTP
ftp = FTP(host='localhost',user='user',passwd='12345')
#设置编码方式,由于在windows系统,设置编码为gbk
ftp.encoding = 'gbk'
#切换目录
ftp.cwd('test')
#列出文件夹的内容
ftp.retrlines('LIST') # ftp.dir()
#下载文件_vimrc
ftp.retrbinary('RETR _vimrc', open('_vimrc', 'wb').write)
#上传文件 _vimrc服务器端文件名为_vimrc3
ftp.storbinary('STOR _vimrc3', open('_vimrc', 'rb'))
#查看目录下的文件详情
for f in ftp.mlsd(path='/test'):
print(f)


来源网址:https://blog.csdn.net/weixin_49345590/article/details/112050079