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

转自:http://www.jb51.net/article/91435.htm

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

本文采取了简单的协议定制,定义了五条命令,指令Head如下:
Sync:标识开始同步文件夹
End:标识结束同步
File:标识传输的文件名(相对路径)
Folder:标志文件夹(相对路径)
None:文件内容

每条命令以CMB_BEGIN开始,以CMB_END结束。

客户端需要对接收缓冲做解析,取出一条一条的指令,然后根据指令的Head做相应的处理,比如创建文件夹、写入文件等。

下面是服务端的代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
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文件夹下的内容全部发送给客户端。

服务端运行结果如下:

下面是客户端的代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
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写入文件时,需要以二进制的方式打开文件,否则,在传输二进制文件时可能出现错误或导致文件损坏。

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值