视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
Python基于Twisted框架的文件夹网络传输源码
2020-11-27 14:16:52 责编:小采
文档
 由于文件夹可能有多层目录,因此需要对其进行递归遍历。

本文采取了简单的协议定制,定义了五条命令,指令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!
")
 
 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!
")
 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写入文件时,需要以二进制的方式打开文件,否则,在传输二进制文件时可能出现错误或导致文件损坏。

经过测试,代码可以正常的运行,文件夹同步成功,文本文件、图像和其他类型的二进制文件均可正常传输。

更多Python 基于Twisted框架的文件夹网络传输源码相关文章请关注PHP中文网!

下载本文
显示全文
专题