ITPub博客

首页 > 应用开发 > Python > Python 基于Twisted框架的文件夹网络传输源码

Python 基于Twisted框架的文件夹网络传输源码

原创 Python 作者:ckxllf 时间:2020-03-17 15:53:20 0 删除 编辑

  由于文件夹可能有多层目录,因此需要对其进行递归遍历。

  本文采取了简单的协议定制,定义了五条命令,指令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() 郑州哪家人流医院好 http://www.zzzyrl120.com/

  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写入文件时,需要以二进制的方式打开文件,否则,在传输二进制文件时可能出现错误或导致文件损坏。

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


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69945560/viewspace-2680954/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2019-08-16

  • 博文量
    204
  • 访问量
    262639