Python基于FTP的小型传输服务器

✨一文搞懂公网文件服务器部署:Python / FTP / WebDAV / Nextcloud 全方案实战 公网服务器、文件服务器、Python HTTP、FTP、WebDAV、Nextcloud、Ubuntu、Linux 运维、文件共享、云盘、自建网盘 阅读详情

前言

因为想要做一个能够满足多用户同时上传/下载文件的功能,并且带有权限功能,网上查了一些资料,尝试了用HTTP协议传输文件,用socket异步IO,多进程传输等方案,从中也学到了很多的东西,这里所述就是使用selectors 和socket模拟FTP协议实现文件的传输,最多可以同时满足10个传输链接。

1.HTTP传输

因为用Django,Flask,Tornado等web框架可以轻松实现文件的上传/下载,这种方法无疑是最容易实现的,我是使用Django做过尝试,但这种方案的问题在于:

  1. 大文件传输过程中可能链接中断
  2. 文件续传的实现比较复杂
  3. 大文件一个链接占用的时间过长


对于大文件上传时可以通过分包的方式上传,让每个包的大小适中,但是HTTP协议毕竟无状态,如果分包,后台任然需要对其进行整合,所以需要频繁的记录传输进度。尝试中文件大小超过20M就可能再传输过程中出现异常(尽管超过20M的可能性很小),从这里引发了思考,想通过别的方式来实现。


2.FTP传输

FTP专为传输文件而生,与HTTP不同,一次传输需要两个TCP链接,一个是命令链接,一个是传输链接,主动模式下,在命令链接进行权限确认等工作,完成后打开传输链接端口并告诉客户端传输链接所在端口,客户端链接传输端口,开始数据传输,这里最大的问题就在与并发问题,命令链接可以用异步IO的方式实现并发,但是传输过程是一对一的,所以要实现多个链接同时上传/下载就需要开启多个端口,小应用还好,大应用就头疼了。被动模式下传输端口由客户端决定,服务器去链接客户端规定的端口,切不说客户端防火墙的问题,这种客户端监听服务器的模式本来就存在很大的问题,但是解决了并发问题。
这里写图片描述
还有一点我觉得安全问题,感觉打开数据连接时可能会被别的链接窃取,当然也可以在数据链路加入一些认证方法。


3.多线程,多进程的异步方式和异步IO

多线程/多进程 简单粗暴,每个链接fork一个子进程或者开启一个子线程来处理,但是这种方法会浪费很多资源在监听链接请求上,并且进程或线程过多,CPU切换线程/进程开销就会加大很多。

异步IO 使用select,poll,epoll来实现异步IO,这种方法通过事件驱动的模式确实能够很好处理并发问题,但是:
比如使用epoll模型,那么每一次传输或者接收到数据后得记录当前传输进度并重新注册事件,实现起来很麻烦。

4.实现

经过思考后,我选择模拟FTP协议,命令链接使用异步IO进行验证和部分信息的获取,获取后开一个线程开启一个数据传输链路进行连接传输。逻辑框图如下:
这里写图片描述

命令链路和传输链路分别占用一个进程,进程间通信使用两个消息队列Queue一个队列中存放端口值(9000,9001……)另外一个存放相关的数据字典,包括文件名,文件大小等,下文简称端口队列,数据队列
命令端口获得连接后,查询端口队列是否为空,不为空则表示任有空闲的传输端口,之后将获得数据放入数据队列,此时传输端口进程监听到数据队列有数据,开启一个线程,线程中套接字绑定到对应传输端口等待客户端的链接,之后进行文件的传输,传输完成后,将本次链接端口号放入端口队列,退出线程。

代码如下:

class FtpServer:
    def __init__(self,**kwds):
        self.IpAddr=kwds['ipaddr']
        self.Port=kwds['port']
        self.QueuePorts=kwds['QueuePorts']
        self.QueueInfors=kwds['QueueInfors']
        self.sel=DefaultSelector()
        self.Socket=socket.socket()
    def connect(self):
        self.Socket.bind((self.IpAddr,self.Port))
        self.Socket.listen(100)
        self.Socket.setblocking(False)
        self.sel.register(self.Socket,EVENT_READ,self.accpet)
        while True:
            events=self.sel.select()
            for key,mask in events:
                callback = key.data
                callback(key.fileobj, mask)
    def accpet(self,sock,mask):
        conn,addr=sock.accept()
        conn.setblocking(False)
        self.sel.register(conn,EVENT_READ,self.interface)

    def Task_Upload(self,conn,size,name):
        Error={}
        if not self.QueuePorts.empty():
            tmp = {}
            tmp['port'] = self.QueuePorts.get()
            tmp['action'] = 'Upload'
            tmp['file_size']=size
            tmp['extra']=name
            self.QueueInfors.put(tmp)  # 将信息传入消息队列 本次连接结束
            conn.send(json.dumps({'status': 'True', 'port': tmp['port'],'size':size}).encode('utf-8'))  # 将本次连接结果返回客户端
        else:
            Error['status'] = False
            Error['reason'] = '服务器资源已占满,请稍后再试'
            package = json.dumps(Error)
            conn.send(package.encode('utf-8'))

    def Task_Download(self,conn,path):
        Error = {}
        if os.path.isfile(path)==False:
            Error['status'] = False
            Error['reason'] = '不存在该路径'
            package = json.dumps(Error)
            conn.send(package.encode('utf-8'))
            return
        if not self.QueuePorts.empty():
            tmp = {}
            tmp['port'] = self.QueuePorts.get()
            tmp['action'] = 'Download'
            tmp['extra'] = path
            tmp['file_size']=os.path.getsize(path)
            self.QueueInfors.put(tmp)  # 将信息传入消息队列 本次连接结束
            conn.send(json.dumps({'status': 'True', 'port': tmp['port'],'size':tmp['file_size']}).encode('utf-8'))  # 将本次连接结果返回客户端
        else:
            Error['status'] = False
            Error['reason'] = '服务器资源已占满,请稍后再试'
            package = json.dumps(Error)
            conn.send(package.encode('utf-8'))


    def interface(self,conn,mask):
        Error={}
        date=None
        try:
            date=conn.recv(1024)
        except Exception as e:
         print(e)
        if date:
            package=json.loads(date.decode('utf-8'))
            action=package.get('action',None)
            paths=package.get('path',None)
            if action=='Download':
                self.Task_Download(conn,paths)
            elif action=='Upload':
                filesize=package.get('filesize',None)
                self.Task_Upload(conn,filesize,package['filename'])
            else:
                Error['status'] = False
                Error['reason'] = '错误的指令'
                package = json.dumps(Error)
                conn.send(package.encode('utf-8'))
        else:
            print('lost connect')
            self.sel.unregister(conn)
            conn.close()

这个是命令链路,进行相关数据的收集,判断是否由空闲端口,并返回一个结果到客户端,包括数据端口等信息。

class TransServer:#需要修的太多 不继承了
    def __init__(self,**kwd):
        self.IpAddr=kwd['ipaddr']
        self.Port=kwd['port']
        self.action=kwd['action']
        self.extra=kwd['extra']
        self.file_size=kwd['file_size']
        self.extra=kwd['extra']
        self.sel = DefaultSelector()
        self.Socket = socket.socket()
        self.block=True

    def connect(self):
        self.Socket.bind((self.IpAddr,self.Port))
        self.Socket.listen(10)
        self.Socket.setblocking(True)
        self.sel.register(self.Socket,EVENT_READ,self.accpet)
        while self.block:
            events=self.sel.select()
            for key,mask in events:
                callback = key.data
                callback(key.fileobj, mask)
        print('端口关闭')
        self.sel.close()#只进行一次连接

    def accpet(self,sock,mask):
        conn,addr=sock.accept()
        conn.setblocking(True)
        if(self.action=='Download'):
            self.sel.register(conn,EVENT_WRITE,self.Download)
        elif(self.action=='Upload'):
            self.sel.register(conn, EVENT_WRITE, self.Upload)
    def BeforeUpload(self,conn):#即将进行上传前
        pass

    def BeforeDownload(self,conn):#即将进行下载前
        pass

    def Upload(self,conn,mask):#处理上传问题
        file_size = self.file_size
        file_name = self.extra
        file = open(SAVEPATH + file_name, 'wb')  # 打开文件夹
        rest_size = file_size
        conn.send('ACK'.encode('utf-8'))
        while rest_size > 0:
            try:

                part = conn.recv(1024 * 1024)
                if part:
                    file.write(part)
                    rest_size -= len(part)
                    print('rest', rest_size)
                else:
                    raise ValueError('传输错误')
            except Exception as e:
                print(e)
                break
        print('task complete')
        self.block = False

    def Download(self,conn,mask):#处理下载问题
        #改进 这里不再需要获取文件相关信息,只需要进行下载
        file = open(self.extra, 'rb')
        file_size=self.file_size
        try:
            date=conn.recv(1024).decode('utf-8')
            if date!='ACK':
                raise ValueError('返回信号不正确')
        except Exception as e:
            print(e)
            self.block=False
            return
        now_size = 0
        for line in file:
            while True:
                try:
                    conn.send(line)
                    now_size += len(line)
                    print('all:%s rest:%s' % (file_size, int(file_size) - now_size))
                    break
                except Exception as e:
                    print(e)
                    self.block = False
                    return
        print('compelet')
        self.block = False

    def AfterUpload(self,conn):#上传完成后
        pass

    def AfterDownload(self,conn):#下载完成后
        pass

数据传输类,完成数据的上传和下载,该链接中只需要一个客户端的响应信号就可以进行传输,不再需要验证和交互,为了减少文件所占用的内存,所以使用分片传输的方法,这里顺带一提的是文件分片传输file.read(size)可以指定读取大小,但是可能出现文件缺失问题,并且内存回收也不好,所以全权交给解释器去完成。

使用方法

def Task_Ftp(*args):
    Ports=args[1]
    infor=args[0]
    x=FtpServer(ipaddr=Host,port=8001,QueuePorts=Ports,QueueInfors=infor)
    try:
        x.connect()
    except Exception as e:
        print(e)
        print('连接中断')



def open_server(*args):
    print('open server',args)
    server=TransServer(ipaddr=Host,port=args[1],action=args[2],extra=args[3],file_size=args[4])
    server.connect()
    print('放回端口到队列中')
    args[0].put(args[1])#端口已经用完了 放回去
def Task_Trans(*args):
    Ports=args[1]
    infor=args[0]#path action
    while True:
        if not infor.empty():
            date=infor.get()
            print('Get Task:%s'%date)
            x = Thread(target=open_server,args=[Ports, date['port'], date['action'], date['extra'],date['file_size']])
            x.start()
            time.sleep(0.2)

if __name__=='__main__':
    s=Queue()#文件路径信息
    b=Queue()#可用端口
    s.empty()
    for i in range(10):#放入开放的端口
        b.put(i+9000)
    CmdServer=Process(target=Task_Ftp,args=[s,b])
    Trans=Process(target=Task_Trans,args=[s,b])
    CmdServer.start()
    Trans.start()
    CmdServer.join()

这里包括了消息队列的创建,线程的启动。

客户端

简单的实现文件:

from socket import socket
import json
import os,sys
import time

SAVEPATH='d://Resource/'

class MyClient:
    def __init__(self,**kwds):
        self._Cmd=socket()
        self._Trans=socket()
        print('Client system init!')
    def _Connect(self,**kwds):
        try:
            self._Cmd.connect((kwds['Ipaddr'],int(kwds['Port'])))
            self.ipaddr=kwds['Ipaddr']
            return True
        except Exception as e:
            print(e)
            return False

    def _CheckPath(self,Path):
        if os.path.isfile(Path):
            return True
        else:
            return False
    def _Cmd_Upload(self,Path,filename):
        date={}
        date['action'] = 'Upload'
        date['filesize']=os.path.getsize(Path)#上传文件大小
        date['filename']=filename
        date=json.dumps(date)#打包成JSON
        self._Cmd.send(date.encode('utf-8'))
        callback=self._Cmd.recv(1024)#接受反馈数据
        callback=json.loads(callback.decode('utf-8'))
        if callback['status']:
            print('服务器响应正确')
            time.sleep(0.5)
            try:
                self._Trans.connect((self.ipaddr,callback['port']))
            except Exception as e:
                print(e)
                print('链接错误')
                return False
            callback=self._Trans.recv(1024)
            if callback.decode('utf-8')!='ACK':
                print('服务器响应不正确 ')
                self._Trans.close()
                return False
            file_size=os.path.getsize(Path)
            file=open(Path,'rb')
            for i in file:
                try:
                    self._Trans.send(i)
                    file_size -= len(i)
                    print('剩余:%s' % file_size)
                except Exception as e:
                    print(e)
                    time.sleep(0.1)
            self._Trans.close()
            print('本次传输完成!')
        else:
            print('Error!')
            print('Reason',callback['reason'])
            return  False
    def _Cmd_Download(self,Path):
        date={}
        date['action']='Download'
        date['path']=Path
        package=json.dumps(date)
        package=package.encode('utf-8')
        self._Cmd.send(package)
        callback=self._Cmd.recv(1024)
        callback=callback.decode('utf-8')
        callback=json.loads(callback)
        if callback['status']=='True':
            file_size=callback['size']
            time.sleep(1)
            try:
                self._Trans.connect((self.ipaddr,callback['port']))
            except Exception as e:
                print(e)
                print('链接失败')
                return
            file=open(SAVEPATH+'test.sm','wb')
            time.sleep(0.5)
            self._Trans.send('ACK'.encode('utf-8'))
            while file_size>0:
                try:
                    date=self._Trans.recv(1024*1024)
                    if date:
                        file_size-=len(date)
                        file.write(date)
                        print('reset:%s'%file_size)
                    else:
                        raise ValueError('传输错误')
                except Exception as e:
                    print(e)
                    print('lost connect')
                    break
            self._Trans.close()
            file.close()
        else:
            print('ERROR')
            print(callback)
            print('reason',callback['reason'])
            return
    def Shell(self):
        while True:
            Ipaddr=input('输入服务器所在ip地址:')
            Port=input('输入服务器端口:')
            print('尝试连接......')
            if self._Connect(Ipaddr=Ipaddr,Port=Port):
                break
        print('连接成功')

        while True:
            Ord=input('1.上传文件\n2.下载文件\n3.退出\n')
            if Ord=='1':
                Path=input('输入本地文件地址(绝对路径):')
                if self._CheckPath(Path):
                    filename = input('输入上传文件名:')
                    self._Cmd_Upload(Path,filename)
                    self._Trans.close()
                    self._Trans=socket()
                else:
                    print('该路径不存在,请检查')
            elif Ord=='2':
                Path=input('输入需要下载的文件地址(绝对路径):')
                self._Cmd_Download(Path)
                self._Trans.close()
                self._Trans=socket()
            elif Ord=='3':
                return
            else:
                print('无效指令')



if __name__=='__main__':
    if os.path.exists(SAVEPATH)==False:
        print('指定的下载存放路径不正确')
        sys.exit(0)
    x=MyClient()
    x.Shell()
    print('Bye!')
    sys.exit(0)

运行后即可按照规定的协议与服务器进行交互。

GitHub

git@github.com:shuhaveabigdream/ftpserver.git

思考

对该项目的测试,我最多只做到了同时3个链接上传/下载,文件最大位1.02GB,都没有什么问题,所以在性能足够的情况下,最多的并发数量应该有端口队列决定,对于身份验证这里并没有进行,可以在FtpServer类中进行扩展,断点传输实现也不困难通过file.seek(ptr)就可以实现,会在后续添加该功能,目前该项目最大的问题在与数据连接的安全问题,如果有第三方不断监听数据链接端口,那么就可能盗取本应由客户端提取的数据,并且传输过程中的控制也并没有实现,不能像如同,监听数据队列的进程依然会占用CPU时间片导致运行效率不高,不能实现FTP命令中的那些流程控制,这些我会在后面继续研究。


尽管做的很青涩,但是从思考到实现的过程中学到了不少的东西,从协议到IO模型到一些性能思考,所以想一万遍始终不如做一遍,用别人做好的东西虽然能够做的更好,更快,但却越过了本应该发现的问题和获得的进步。

FTP上传代码到服务器,用Docker容器化部署的完整流程 容器化部署是现代应用交付的基础能力,Docker通过镜像封装应用及其依赖,实现环境一致性,而FTP/SFTP则是轻量级文件传输的常见手段。理解容器运行原理、镜像构建流程和端口映射机制,能帮助开发者快速上手服务发布。在无CI/CD环境的小型项目中,FTP上传加Docker部署是效率与稳定性的平衡点,适用于个人博客、小型API和临时演示环境。本文从概念到实践,梳理了从本地代码上传、Dockerfile编写、镜像构建到容器运行的完整链路,并针对端口冲突、权限问题等高频故障给出排查思路,为轻量应用的快速上线提供了一 阅读详情

相关推荐

FTP协议深度解析:从双通道原理到现代安全实践

文件传输协议(FTP)作为网络文件交换的基础标准,定义了客户端与服务器之间通过控制连接和数据连接进行通信的机制。其核心在于双通道设计:控制连接负责命令传输,数据连接专用于文件内容交换。这种分离架构确保了会话的连续性与资源高效利用。在技术价值上,FTP实现了跨平台文件的可靠传输,支撑了早期互联网的内容分发。然而,由于明文传输等安全缺陷,现代实践中更推荐使用基于SSL/TLS的FTPS或基于SSH的SFTP协议。在应用场景中,FTP仍常见于网站维护、内网文件共享及遗留系统对接。例如,通过docker部署ftp服

weixin_34405557的博客 425

Python 项目一 FTP服务器

server端 from socket import * import os import time FILE_PATH = 'usr/bin' class FtpServer(object): def __init__(self, connfd): self.connfd = connfd def do_list(self): filelist = os.listdir(F...

smart boy 264

FTP上传代码+Docker部署:从本地到服务器的完整实践指南

在软件交付过程中,环境一致性是开发者普遍面临的挑战。本地运行正常的应用,部署到服务器后常因依赖冲突、系统差异或进程管理问题而失败。Docker 通过镜像与容器技术,将应用及其运行环境打包成标准化单元,从根本上解决了“在我电脑上是好的”这类问题;而 SFTP/FTP 作为常见的文件传输协议,为代码上传提供了轻量、直接的通道。理解镜像、容器、Dockerfile 等基础概念,掌握端口映射与数据持久化原理,是构建可靠部署流程的关键。无论是个人项目、中小团队,还是临时交付场景,将 SFTP 传输与 Docker 容

weixin_34411563的博客 332

python3 ftp服务器_python3实现ftp服务功能(服务端 For Linux)

本文实例为大家分享了python3实现ftp服务功能的具体代码,供大家参考,具体内容如下功能介绍:可执行的命令:lspwdcdputrmgetmkdir1、用户加密认证2、允许多用户同时登陆3、每个用户有自己的家目录,且只可以访问自己的家目录4、运行在自己家目录下随意切换目录5、允许上传下载文件,且文件一致6、传输过程中显示进度条server main 代码:# Author by Andy# _...

weixin_39634997的博客 471

【雕爷学编程】MicroPython手册之 WiPy FTP 服务器

然而,你可以在WiPy设备上运行一个FTP服务器,比如通过使用一些更复杂的嵌入式Python环境(不一定直接在WiPy上,也可以在类似树莓派等更强大的设备上运行Python来作为FTP服务器),或者使用一些专门为这个目的设计的第三方库。它的设计目标是提供一个紧凑、低功耗的硬件平台,能够运行MicroPython这样的高级编程语言,并具备连接到互联网和其他设备的能力。FTP是一种复杂的协议,需要服务器端和客户端两方面的支持,而在MicroPython的WiPy设备上实现FTP服务器可能会相当复杂。

雕爷学编程 343

python实现ftp文件传输系统(案例分析)

最近做了一个简单的文件传输系统,基于ftp协议,使用python语言开发,虽然python里面已经有ftplib模块,可以很容易的实现ftp服务器。这次我使用的是socket实现client与ftp server之间的通讯和文件传输,client另起一个flask服务器,用于用户在浏览器端的交互。系统实现的功能有:用户登录注册,用户查看ftp服务器端文件和下载上传删除操作,支持多进程、多用户。 一,登录注册          该项目使用的是mongo数据库,其实用户登录注册功能很好实现,没有什么技术细节,这里就略过了。数据库管理代码如下: import pymongo from pymong

实现model中的文件上传FTP(一)

由于在django的model中配置了filefield或者imagefield配置了upload_to参数只能将用户上传的文件上传到项目本地,就算重定向到项目外也只是直接读取文件系统,这样对未来的项目迁移或者资源管理都会造成很大的困扰,而且这种方式总觉得不太符合规范,所以找了一些资料将文件上传直接上传到FTP 一.django-storages django的存储是通过一个叫做storage...

weixin_30747253的博客 519

Python实现FTP上传文件或文件夹实例(递归)

本篇文章主要介绍了Python实现FTP上传文件或文件夹实例(递归),具有一定的参考价值,有兴趣的可以了解一下。

通过 Python 【FTP】实现文件上传与下载(含源码)

Python 通过FTP实现文件上传与下载【含代码】。

weixin_53575943的博客 2541

AUTOSAR入门

一、AUTOSAR是什么 AUTOSAR组织自己的介绍是 AUTOSAR (AUTomotive Open System ARchitecture) is a worldwide development partnership of vehicle manufacturers, suppliers, service providers and companies from the automot...

天涯遍地是小草的博客 3万+

墨水屏高效开发:架构、开源库与实战优化指南

嵌入式显示技术中,电子墨水屏以其类纸观感和超低功耗特性,在电子书阅读器、智能办公本及工业仪表等场景中占据独特地位。其工作原理基于微胶囊电泳技术,仅在画面刷新时消耗电能,静态显示时功耗近乎为零,这带来了极致的续航优势。为实现流畅的交互体验,开发者需构建分层渲染架构,通过硬件抽象层统一驱动接口,并引入帧缓冲与差异比较算法智能决策局部刷新区域,从而大幅降低刷新延迟与功耗。开源库如GxEPD2和LVGL为墨水屏适配提供了关键支持,结合波形文件管理与电源优化策略,能有效解决残影与卡顿问题。本文聚焦于eink墨水屏高效

weixin_42545636的博客 410

django传送文件夹到服务器,Django上传文件代码

在django里面上传文件views.py# Create your views here.# coding=utf-8from django.http import HttpResponse,HttpResponseRedirectfrom django.shortcuts import render_to_responsefrom django.template import RequestC...

weixin_35651612的博客 446

TwinCAT3 实时核异步通信:基于ADS的C++ Server/Client数据交换实战解析

本文深入解析了在TwinCAT3实时核中,如何利用ADS协议实现C++ Server与Client之间的异步数据交换。文章从核心概念入手,详细阐述了实时核、ADS通信及异步机制,并通过实战步骤指导环境搭建、路由配置、Server端服务创建与Client端请求发起,重点剖析了Req/Ind/Res/Con异步回调模型,旨在帮助开发者构建高效、非阻塞的实时工业控制应用。

purple的博客 468

Python FTP服务器终极指南:PyFTPdLib快速部署与实战应用

PyFTPdLib是一个极其快速且可扩展的Python FTP服务器库,它允许开发者轻松构建高性能的FTP服务。本文将为你提供从安装到实战应用的完整指南,帮助你快速掌握这个强大工具的使用方法。 ## 为什么选择PyFTPdLib? PyFTPdLib作为一个纯Python实现的FTP服务器库,具有以下显著优势: - **卓越性能**:采用异步I/O模型,处理并发连接效率高 - **易于使用*

gitblog_00585的博客 684

拯救者Y9000P 2022双系统实战:Ubuntu22.04分区优化与驱动避坑指南

本文提供联想拯救者Y9000P 2022款安装Ubuntu 22.04双系统的详细实战指南。重点讲解针对该机型的磁盘分区优化方案、NVIDIA显卡驱动安装避坑技巧,以及安装后的网络、时间同步等必备配置,帮助用户高效完成双系统部署并提升使用体验。

weixin_29208327的博客 422

Windows显卡TDR超时导致Unity崩溃?手把手教你修改注册表延长响应时间

本文详细解析了Windows显卡TDR超时导致Unity崩溃的问题,并提供了修改注册表延长响应时间的完整解决方案。通过调整TdrDelay和TdrDdiDelay键值,开发者可以有效避免D3D11设备丢失错误,提升Unity编辑器的稳定性。文章还包含显卡驱动优化、系统性能调优等实用技巧,帮助开发者彻底解决编辑器崩溃问题。

weixin_33737774的博客 621

PyFTPdLib:打造高性能Python FTP服务器的终极选择

PyFTPdLib是一个极其快速且可扩展的Python FTP服务器库,它为开发者提供了构建高性能FTP服务的强大工具。无论是用于文件共享、数据传输还是自动化备份,PyFTPdLib都能满足各种场景需求,成为Python开发者构建FTP服务器的首选解决方案。 ## 🚀 为什么选择PyFTPdLib? ### 卓越的性能表现 PyFTPdLib以其出色的性能而闻名,采用高效的异步I/O模型,能

gitblog_00640的博客 670

Windows下飞桨PaddlePaddle 2.6.1 GPU版环境搭建全攻略(含CUDA 11.7配置避坑指南)

本文详细介绍了在Windows系统下搭建飞桨PaddlePaddle 2.6.1 GPU版环境的完整流程,特别针对CUDA 11.7和cuDNN的安装提供了避坑指南。从Anaconda环境配置、CUDA Toolkit安装到飞桨GPU版的验证,手把手帮助开发者高效完成深度学习环境搭建,解决常见问题并优化性能。

x8y9z0的博客 1094

别在用vsftp啦!这个python包能灵活托管ftp的一切!

是一个基于 Python 的 FTP 服务器实现库,适合用来开发定制化 FTP 服务器。

rock---you的博客 577

WblockCloneObjects克隆一个图纸内的实体包括块参照,同名块参照的处理

public static void HeBingTu2(double lieJu, List<string> filePaths) { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; using (DocumentLock docLock = doc.Lock...

1108

TOGAF架构内容—TOGAF 内容框架和企业元模型

TOGAF架构内容—TOGAF 内容框架和企业元模型

深圳市多克创新科技有限公司 1663

使用python快速搭建HTTP服务实现局域网网页浏览或文件传输

请注意,这只是一个简单的示例,适用于局域网内部的临时使用。如果你想实现文件传输功能,你可以将要共享的文件放在该脚本所在目录,然后使用浏览器访问相应的文件。例如,如果你的服务器脚本和要共享的文件都在同一个目录下,你可以使用浏览器访问。文件,然后在终端中运行该文件,你的HTTP服务器就会在指定的端口(例如8000)上运行。如果你已经在局域网中有一个Web服务器,你可以将文件放置在服务器的网站目录中,然后通过服务器的IP地址来访问。如果想要在局域网内的其他设备上访问,需要使用运行服务器的计算机的IP地址,例如。

m0_57021623的博客 5203

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

探索PyFTP: 一款基于PyQt的FTP服务器与客户端利器

探索PyFTP: 一款基于PyQt的FTP服务器与客户端利器 在互联网协议的世界里,FTP(文件传输协议)作为数据交换的经典方式之一,至今仍占据着一席之地。今天,我们来探索一个由Jack Lam创建的开源项目——PyFTP,这是一款融合了PyQt框架魅力和FTP协议精髓的工具,旨在帮助开发者和用户更轻松地进行文件传输任务。 PyFTP项目简介 PyFTP是一个利用Qt框架打造的FTP服务器和客户端...

gitblog_00061的博客 556

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

随笔录--使用python快速搭建HTTP服务实现局域网网页浏览或文件传输

使用python快速搭建HTTP服务实现局域网网页浏览或文件传输

Bigbin666的博客 1091

Python之Simple FTP (一)

一、引言:   好久之前想写一个ftpserver的小daemon,但是一直拖着就没有写,这回正好处于放假的时候可以有时间来写写。 二、FTP需求功能:   1、用户认证系统   2、文件上传和下载功能     a、支持断点续传     b、传输中显示进度条   3、支持tab,历史命令回看功能   4、支持ls/cd命令   6、logging日志记录   三、必备知识:    1、Socket...

weixin_33720956的博客 533

copyparty:断了能接着传的文件服务器

copyparty 是一个便携的 Python 文件服务器:装完一个包就能让任意目录通过浏览器、WebDAV、FTP 等方式对外分享,并且上传支持断点续传。如果你需要把文件快速传给局域网里的其他设备,又受够了传输中断后从头再来,这个项目就是为此做的。 ## 卡在 80% 的传输 你把一部 40GB 的电影从手机往电脑传,传到 80% 网络抖了一下,连接断了。重新发起传输,进度条回到零。你只想在

gitblog_00864的博客 904
上一篇: Python3.x调用阿里云短信api
下一篇: 数据结构之二叉树
shu_8708
博客等级 码龄10年 45粉丝 40原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值