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

作者:ian 时间:2021-03-19 03:01:00 

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

本文采取了简单的协议定制,定义了五条命令,指令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文件夹下的内容全部发送给客户端。

服务端运行结果如下:

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

下面是客户端的代码:


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的文件夹进行同步。

客户端运行结果如下:

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

需要注意的地方:
Client写入文件时,需要以二进制的方式打开文件,否则,在传输二进制文件时可能出现错误或导致文件损坏。

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

来源:http://www.icodelogic.com/?p=516

标签:Twisted,文件夹网络,传输源码
0
投稿

猜你喜欢

  • 最近写的一个asp缓存函数

    2008-11-25 14:07:00
  • ASP中双引号单引号和&连接符使用技巧

    2007-10-01 18:20:00
  • 简单的网站页面有什么好处

    2007-11-15 06:28:00
  • asp随机生成文件名的函数

    2009-02-11 13:41:00
  • python的函数和方法(上)

    2021-02-04 11:46:16
  • 利用后缀表达式(逆波兰式)算24点的JavaScript版算法

    2010-01-23 10:57:00
  • Dreamweaver实现flash透明背景

    2008-05-04 09:35:00
  • 在ASP.NET 2.0中操作数据之五十五:编辑和删除现有的二进制数据

    2023-07-10 02:05:43
  • 新兴XML处理方法VTD-XML介绍

    2008-09-04 14:42:00
  • Oracle学习笔记(一)

    2012-01-05 18:51:44
  • 如何编写一个高效的国税系统通讯录数据库?

    2009-11-07 18:53:00
  • 使用批处理实现mysql的数据库备份与上传

    2012-01-05 19:30:23
  • 浅析Go设计模式之Facade(外观)模式

    2023-07-16 19:23:08
  • 标签水平右对齐更适合中文网站

    2009-05-01 11:54:00
  • 想用户所想(感受亚马逊的设计)

    2007-08-26 17:09:00
  • “Unable to read local eventlog (reason:事件日志文件已在读取时间更改)”解决办法

    2009-08-27 13:12:00
  • 10条影响CSS渲染速度的写法与建议

    2008-09-09 22:02:00
  • PHPExcel冻结(锁定)表头的简单实现方法

    2023-08-18 02:35:21
  • 23条科学设计你网站的方法

    2008-03-23 14:12:00
  • 20行python代码的入门级小游戏的详解

    2023-07-15 01:25:31
  • asp之家 网络编程 m.aspxhome.com