当前位置: 首页 > 后端技术 > Python

使用python搭建一个基于socket的文件(文件夹)传输系统

时间:2023-03-26 11:07:36 Python

这段时间在学习python,在网络编程中接触到了socket,所用的linux服务器都是原生支持python,于是有了做一个文件传输功能程序的想法。毕竟在python语言中,带有下载功能的框架还是很多的,但是在宿主机和宿主机之间快速搭建一个文件(文件夹)传输通道的程序好像并不多见,因为我刚被接触过python,不知不觉也不足为奇,总的来说,自己动手练一把,很有成就感。项目地址https://github.com/Ccapton/py...从本地主机发送文件到远程服务器主机的实用预览。思维导图文件传输系统以上思维导图仅供参考。毕竟表达能力有限,具体功能还是要追溯到代码,分析其原理。原理是基于socket通信。相信会编程的朋友都不会陌生。通过套接字传输文件也很常见,但这只是针对单个文件很容易实现。多个文件呢?在实施这个系统之前,我尝试了几次。使用单个socket通道传输多个文件是不切实际的,因为在调用socket.recv()方法时,返回的数据格式是原始数据str类型,不同文件的数据需要分流,很不方便难的。因为涉及到收发双方文件数据收发进度的统一,需要使用额外的指令来控制传输工作不乱,所以想到多开一个socket作为传输指令的通道,方便指令和数据的传输。分开,很容易控制传输工作!所以有指令线程和数据线程。转移整个文件夹,首先要遍历文件夹,准确还原里面的所有文件结构;因为数据是通过socket传输的,所以文件只能一个一个传输。这样,文件的遍历工作只能在前面的文件传输完成后才能继续,所以需要重新设计遍历工作。修改后,我在文件查找器(遍历)中添加了一个while循环体和一个外部继承的回调类,这样就可以达到我想要的文件通过socket顺序传输的效果。文件查找器FileFinder(阻塞式)源码:importos,time#文件和文件夹搜索类(阻塞式)#阻塞式设计:为了等待调用者的耗时操作【否则文件遍历任务很快完成,调用者无法实现顺序操作文件(文件夹)的意图]classFileFinder:def__init__(self,finderCallback):self.finderCallback=finderCallback#文件(文件夹)路径下所有文件的总大小self.sum_size=0#CallerControl参数,如果为False,则继续遍历工作,如果为True,则阻塞任务,等待调用者完成其其他耗时操作后再考虑是否更改该值self.recycle=True#caller-controlledparameter如果为False,则正常工作。如果为True,当recycle为False时,遍历工作不会阻塞,快速完成。当recycle为True时,遍历工作将被阻塞。FinderCallback:#查找文件夹defonFindDir(self,dir_path):pass#查找文件defonFindFile(self,file_path,size):pass#保留刷新函数defonRefresh(self):pass#查找文件(文件夹)方法deflist_flie(self,root_dir):如果os.path.isfile(root_dir):而self.recycle:time.sleep(0.05)如果self.finderCallback:self.finderCallback.onFindFile(root_dir,os.path.getsize(root_dir))self.finderCallback.onRefresh()ifnotself.off:self.recycle=Trueelse:dirlist=os.listdir(root_dir)#列出文件夹下所有的目录与文件fordirindirlist:path=os.path.join(root_dir,dir)ifos.path.isfile(path):whileself.recycle:time.sleep(0.05)ifself.finderCallback:self.finderCallback.onFindFile(path,os.path.getsize(path))self.finderCallback.onRefresh()如果不是self.off:self.recycle=Trueelse:whileself.recycle:time.sleep(0.05)ifself.finderCallback:self.finderCallback.onFindDir(path)self.finderCallback.onRefresh()如果不是self.off:self.recycle=True#递归调用(遍历到文件夹时,继续遍历,直到当前文件夹下没有文件夹)self.list_flie(path)重写其onFindDir(self,dir_path)和onFindFile(self,file_path,size)方法,在这两个方法中向接收端发送相关命令,但是最难的是两端命令线程中socket命令信息的处理,需要深入代码详细研究,本人能力有限,所以我不会详细介绍。注意,要在接收端运行程序,需要一个可以访问的地址,也就是说最好在局域网内进行文件传输工作,因为局域网的本地IP可以直接访问。如果是公网传输文件,必须知道接收主机公网ip和私网ip。比如我使用的接收主机是腾讯云的主机,内网ip是10.135.xxx.xxx,公网ip是111.120.xxx.xxx。在这个主机上,运行接收(服务器)程序python3ftserver.py-i10.135.xxx.xxx-d/home/ubuntu/downloads并在你的主机上运行发送(客户端)程序来发送文件夹bilibilipython3ftclient.py-i111.120.xxx.xxx-f/Users/capton/desktop/bilibili由于腾讯云、阿里云等国内虚拟主机提供商采用NAT地址转换为云主机分配地址,所以按照上面的步骤运行两个终端程序可以连接。