Python 基于Twisted框架的文件夹网络传输源码
作者:ian 发布时间:2021-03-19 03:01:00
标签:Twisted,文件夹网络,传输源码
由于文件夹可能有多层目录,因此需要对其进行递归遍历。
本文采取了简单的协议定制,定义了五条命令,指令Head如下:
Sync:标识开始同步文件夹
End:标识结束同步
File:标识传输的文件名(相对路径)
Folder:标志文件夹(相对路径)
None:文件内容
每条命令以CMB_BEGIN开始,以CMB_END结束。
客户端需要对接收缓冲做解析,取出一条一条的指令,然后根据指令的Head做相应的处理,比如创建文件夹、写入文件等。
下面是服务端的代码:
from twisted.internet import reactor
from twisted.internet.protocol import Protocol,Factory
from twisted.protocols.basic import LineReceiver
import os
import struct
BUFSIZE = 4096
class SimpleLogger(Protocol):
def connectionMade(self):
print 'Got connection from', self.transport.client
def connectionLost(self, reason):
print self.transport.client, 'disconnected'
def dataReceived(self, line):
print line
self.transport.write("Hello Client, I am the Server!\r\n")
self.transport.write("CMB_BEGIN")
self.transport.write("Sync")
self.transport.write("CMB_END")
self.send_file_folder('server')
def send_file_folder(self,folder):
'''send folder to the client'''
for f in os.listdir(folder):
sourceF = os.path.join(folder, f)
if os.path.isfile(sourceF):
print 'File:',sourceF[7:]
self.transport.write("CMB_BEGIN")
self.transport.write("File:" + sourceF[7:])
self.transport.write("CMB_END")
fp = open(sourceF,'rb')
while 1:
filedata = fp.read(BUFSIZE)
if not filedata: break
else:
self.transport.write("CMB_BEGIN")
self.transport.write(filedata)
print 'send size:::::::::',len(filedata)
self.transport.write("CMB_END")
fp.close()
self.transport.write("CMB_BEGIN")
self.transport.write("End")
self.transport.write("CMB_END")
if os.path.isdir(sourceF):
print 'Folder:',sourceF[7:]
self.transport.write("CMB_BEGIN")
self.transport.write("Folder:" + sourceF[7:])
self.transport.write("CMB_END")
self.send_file_folder(sourceF)
factory = Factory()
factory.protocol = SimpleLogger
reactor.listenTCP(1234, factory)
reactor.run()
Server在收到Client的某个信号之后(此代码中,当Client随便向Server发送任何内容都可),Server即会调用send_file_folder将sever文件夹下的内容全部发送给客户端。
服务端运行结果如下:
下面是客户端的代码:
from twisted.internet.selectreactor import SelectReactor
from twisted.internet.protocol import Protocol,ClientFactory
from twisted.protocols.basic import LineReceiver
import os
from struct import *
reactor = SelectReactor()
protocol = Protocol()
prepare = 0
filename = ""
sourceDir = 'client'
recvBuffer = ''
def delete_file_folder(src):
'''delete files and folders'''
if os.path.isfile(src):
try:
os.remove(src)
except:
pass
elif os.path.isdir(src):
for item in os.listdir(src):
itemsrc = os.path.join(src,item)
delete_file_folder(itemsrc)
try:
os.rmdir(src)
except:
pass
def clean_file_folder(src):
'''delete files and child folders'''
delete_file_folder(src)
os.mkdir(src)
def writefile(filename,data):
print 'write file size:::::::::',len(data)
fp = open(filename,'a+b')
fp.write(data)
fp.close()
class QuickDisconnectedProtocol(Protocol):
def connectionMade(self):
print "Connected to %s."%self.transport.getPeer().host
self.transport.write("Hello server, I am the client!\r\n")
def dataReceived(self, line):
global prepare
global filename
global sourceDir
global recvBuffer
recvBuffer = recvBuffer + line
self.processRecvBuffer()
def processRecvBuffer(self):
global prepare
global filename
global sourceDir
global recvBuffer
while len(recvBuffer) > 0 :
index1 = recvBuffer.find('CMB_BEGIN')
index2 = recvBuffer.find('CMB_END')
if index1 >= 0 and index2 >= 0:
line = recvBuffer[index1+9:index2]
recvBuffer = recvBuffer[index2+7:]
if line == 'Sync':
clean_file_folder(sourceDir)
if line[0:3] == "End":
prepare = 0
elif line[0:5] == "File:":
name = line[5:]
filename = os.path.join(sourceDir, name)
print 'mk file:',filename
prepare = 1
elif line[0:7] == "Folder:":
name = line[7:]
filename = os.path.join(sourceDir, name)
print 'mkdir:',filename
os.mkdir(filename)
elif prepare == 1:
writefile(filename,line)
else:
break
class BasicClientFactory(ClientFactory):
protocol=QuickDisconnectedProtocol
def clientConnectionLost(self,connector,reason):
print 'Lost connection: %s'%reason.getErrorMessage()
reactor.stop()
def clientConnectionFailed(self,connector,reason):
print 'Connection failed: %s'%reason.getErrorMessage()
reactor.stop()
reactor.connectTCP('localhost',1234,BasicClientFactory())
reactor.run()
客户端提取出来自Server的指令,当提取出Sync指令时,则将sourceDir目录清空,然后根据后续的指令,跟Server的文件夹进行同步。
客户端运行结果如下:
需要注意的地方:
Client写入文件时,需要以二进制的方式打开文件,否则,在传输二进制文件时可能出现错误或导致文件损坏。
经过测试,代码可以正常的运行,文件夹同步成功,文本文件、图像和其他类型的二进制文件均可正常传输。
来源:http://www.icodelogic.com/?p=516


猜你喜欢
- LSTM介绍关于LSTM的具体原理,可以参考:https://www.jb51.net/article/178582.htmhttps://
- 因为主键可以唯一标识某一行记录,所以可以确保执行数据更新、删除的时候不会出现张冠李戴的错误。当然,其它字段可以辅助我们在执行这些操作时消除共
- 写给新手的话pycharm是什么,为什么让我指定interpreter记事本最开始写C语言代码的时候,人们使用vi,记事本等软件写代码,写完
- 小引 笔者认为web开发包括设计html,javascript,css,以及一种高级语言,比如c#,java等等,本文分为三部分,第一部分为
- 1、$nextTickvm.$nextTick( [callback] )this.$nextTick()将回调延迟到下次 DOM 更新循环
- 1.Django实现WebSocket在线聊天室1.1 安装pip install channels==2.3(saas) F:\Deskt
- 多属性排序:把需要排序的属性拿出来作为一个 tuple,主要的放前面,次要的放后面。假如某对象有n个属性,那么先按某规则对属性a进行排序,在
- 使用场景已搭建了PyPI私有库,上传公共库包含静态文件,如需要使用sql静态文件初始化数据库。打包python包,给其他人使用,但项目中包含
- eval()函数eval() 函数用来执行一个字符串表达式,并返回表达式的值。语法eval(expression[, globals[, l
- 创建类from django.forms import ModelFormfrom django.forms import widgets
- 我就废话不多说了,直接上代码了。非常简单哦!pytorch转成longtensorb = torch.rand(3,3)#得到的是float
- 技术背景对于各行各业的研究人员来说,经常会面临这样的一个问题:有一篇不错的文章里面有很好的数据,但是这个数据在文章中仅以图片的形式出现。而假
- 前言:PyPDF2是一个纯Python的开源库,能够分割或合并PDF文件,也可以裁剪或转换PDF文件中的页面。我们还可以使用PyPDF2查看
- select user_name,count(*) as count from user_table group by user_name
- 在运营或者对各种 SDK 或者 API 进行调试的时候,邮件功能基本上都会被使用到。在测试的时候,可能很多人都会使用 SMTP 或者自己的邮
- 本文实例讲述了Python Django中间件,中间件函数,全局异常处理操作。分享给大家供大家参考,具体如下:应用名/middleware.
- Update Tb_Garden1 G Set Steward = (Select Id From Zyq.Tb_User U Where
- 本文为大家分享了MySQL 8.0.29 安装配置方法图文教程,供大家参考,具体内容如下一、下载MySQL1、进入MySQL官网MySQL并
- 代码使用说明1970-2270文件夹是保存图像和json文件(也就是需要进行转换的文件)det文件夹是保存单个json对应的txt(因为np
- 简单定义图轴:import numpy as npimport matplotlib.pyplot as plt创建一个简单的matplot