You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于pyftpdlib的多线程FTP服务器阻塞问题求助

问题分析与解决提示

核心问题1:并发配置代码未生效

你的server.max_cons和server.max_cons_per_ip设置写在了server.serve_forever()之后,而serve_forever()是阻塞调用,程序执行到这里就会一直停留在服务器循环中,后面的配置代码永远不会被执行。这直接导致服务器没有启用你期望的并发连接限制,默认的并发设置可能无法满足多线程并行需求。

核心问题2:文件接收后的阻塞操作占用连接线程

on_file_received方法是在当前FTP连接对应的线程中执行的,如果你在这个方法里做time.sleep(2)这类阻塞操作,会直接占用该连接的线程,导致同一个连接下的后续文件上传请求必须等待当前阻塞操作完成才能处理。即使是不同客户端的连接,若并发参数未正确设置,也会出现串行处理的情况。

修复方案

  1. 调整并发配置的位置:把server.max_cons和server.max_cons_per_ip的设置移到server.serve_forever()之前,确保配置生效。
  2. 将耗时操作移到独立线程:把on_file_received中的阻塞逻辑放到单独的线程中执行,避免占用FTP连接线程,让服务器可以立即处理其他上传请求。

修改后的代码

from pyftpdlib.handlers import FTPHandler
from pyftpdlib.servers import ThreadedFTPServer
from pyftpdlib.authorizers import DummyAuthorizer
import os
import time
import threading


class MyHandler(FTPHandler):

    def on_file_received(self, file):
        # 定义耗时处理的函数,放到独立线程执行
        def process_file(file_path):
            f = os.path.basename(file_path)
            print("start %s" % f)
            time.sleep(2)
            print("ended %s" % f)
            os.remove(file_path)
        
        # 启动新线程处理,不阻塞当前连接线程
        threading.Thread(target=process_file, args=(file,), daemon=True).start()


def main():
    authorizer = DummyAuthorizer()
    authorizer.add_user('test', 'test','/temp', perm='elradfmwM')

    handler = MyHandler
    handler.authorizer = authorizer
    server = ThreadedFTPServer(('', 21), handler)
    
    # 先设置并发参数,再启动服务器
    server.max_cons = 256
    server.max_cons_per_ip = 5
    
    server.serve_forever()


if __name__ == "__main__":
    main()

额外说明

  • 使用daemon=True创建线程,确保当主进程退出时,这些处理线程会自动终止,避免残留僵尸线程。
  • 如果需要支持单个客户端同时上传多个文件,客户端需要建立多个FTP连接(比如使用多线程客户端),因为单个FTP控制连接下的文件上传默认是串行的,这是FTP协议的特性,和服务器的多线程实现无关。

内容的提问来源于stack exchange,提问作者Daniel U

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 08:53:10