当前位置:Gxlcms > Python > Python基于Twisted框架的文件夹网络传输源码

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

时间:2021-07-01 10:21:17 帮助过:38人阅读

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

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

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

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

下面是服务端的代码:

  1. from twisted.internet import reactor
  2. from twisted.internet.protocol import Protocol,Factory
  3. from twisted.protocols.basic import LineReceiver
  4. import os
  5. import struct
  6. BUFSIZE = 4096
  7. class SimpleLogger(Protocol):
  8. def connectionMade(self):
  9. print 'Got connection from', self.transport.client
  10. def connectionLost(self, reason):
  11. print self.transport.client, 'disconnected'
  12. def dataReceived(self, line):
  13. print line
  14. self.transport.write("Hello Client, I am the Server!\r\n")
  15. self.transport.write("CMB_BEGIN")
  16. self.transport.write("Sync")
  17. self.transport.write("CMB_END")
  18. self.send_file_folder('server')
  19. def send_file_folder(self,folder):
  20. '''send folder to the client'''
  21. for f in os.listdir(folder):
  22. sourceF = os.path.join(folder, f)
  23. if os.path.isfile(sourceF):
  24. print 'File:',sourceF[7:]
  25. self.transport.write("CMB_BEGIN")
  26. self.transport.write("File:" + sourceF[7:])
  27. self.transport.write("CMB_END")
  28. fp = open(sourceF,'rb')
  29. while 1:
  30. filedata = fp.read(BUFSIZE)
  31. if not filedata: break
  32. else:
  33. self.transport.write("CMB_BEGIN")
  34. self.transport.write(filedata)
  35. print 'send size:::::::::',len(filedata)
  36. self.transport.write("CMB_END")
  37. fp.close()
  38. self.transport.write("CMB_BEGIN")
  39. self.transport.write("End")
  40. self.transport.write("CMB_END")
  41. if os.path.isdir(sourceF):
  42. print 'Folder:',sourceF[7:]
  43. self.transport.write("CMB_BEGIN")
  44. self.transport.write("Folder:" + sourceF[7:])
  45. self.transport.write("CMB_END")
  46. self.send_file_folder(sourceF)
  47. factory = Factory()
  48. factory.protocol = SimpleLogger
  49. reactor.listenTCP(1234, factory)
  50. reactor.run()

Server在收到Client的某个信号之后(此代码中,当Client随便向Server发送任何内容都可),Server即会调用send_file_folder将sever文件夹下的内容全部发送给客户端。

服务端运行结果如下:

24.jpg

下面是客户端的代码:

  1. from twisted.internet.selectreactor import SelectReactor
  2. from twisted.internet.protocol import Protocol,ClientFactory
  3. from twisted.protocols.basic import LineReceiver
  4. import os
  5. from struct import *
  6. reactor = SelectReactor()
  7. protocol = Protocol()
  8. prepare = 0
  9. filename = ""
  10. sourceDir = 'client'
  11. recvBuffer = ''
  12. def delete_file_folder(src):
  13. '''delete files and folders'''
  14. if os.path.isfile(src):
  15. try:
  16. os.remove(src)
  17. except:
  18. pass
  19. elif os.path.isdir(src):
  20. for item in os.listdir(src):
  21. itemsrc = os.path.join(src,item)
  22. delete_file_folder(itemsrc)
  23. try:
  24. os.rmdir(src)
  25. except:
  26. pass
  27. def clean_file_folder(src):
  28. '''delete files and child folders'''
  29. delete_file_folder(src)
  30. os.mkdir(src)
  31. def writefile(filename,data):
  32. print 'write file size:::::::::',len(data)
  33. fp = open(filename,'a+b')
  34. fp.write(data)
  35. fp.close()
  36. class QuickDisconnectedProtocol(Protocol):
  37. def connectionMade(self):
  38. print "Connected to %s."%self.transport.getPeer().host
  39. self.transport.write("Hello server, I am the client!\r\n")
  40. def dataReceived(self, line):
  41. global prepare
  42. global filename
  43. global sourceDir
  44. global recvBuffer
  45. recvBuffer = recvBuffer + line
  46. self.processRecvBuffer()
  47. def processRecvBuffer(self):
  48. global prepare
  49. global filename
  50. global sourceDir
  51. global recvBuffer
  52. while len(recvBuffer) > 0 :
  53. index1 = recvBuffer.find('CMB_BEGIN')
  54. index2 = recvBuffer.find('CMB_END')
  55. if index1 >= 0 and index2 >= 0:
  56. line = recvBuffer[index1+9:index2]
  57. recvBuffer = recvBuffer[index2+7:]
  58. if line == 'Sync':
  59. clean_file_folder(sourceDir)
  60. if line[0:3] == "End":
  61. prepare = 0
  62. elif line[0:5] == "File:":
  63. name = line[5:]
  64. filename = os.path.join(sourceDir, name)
  65. print 'mk file:',filename
  66. prepare = 1
  67. elif line[0:7] == "Folder:":
  68. name = line[7:]
  69. filename = os.path.join(sourceDir, name)
  70. print 'mkdir:',filename
  71. os.mkdir(filename)
  72. elif prepare == 1:
  73. writefile(filename,line)
  74. else:
  75. break
  76. class BasicClientFactory(ClientFactory):
  77. protocol=QuickDisconnectedProtocol
  78. def clientConnectionLost(self,connector,reason):
  79. print 'Lost connection: %s'%reason.getErrorMessage()
  80. reactor.stop()
  81. def clientConnectionFailed(self,connector,reason):
  82. print 'Connection failed: %s'%reason.getErrorMessage()
  83. reactor.stop()
  84. reactor.connectTCP('localhost',1234,BasicClientFactory())
  85. reactor.run()

客户端提取出来自Server的指令,当提取出Sync指令时,则将sourceDir目录清空,然后根据后续的指令,跟Server的文件夹进行同步。

客户端运行结果如下:

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

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

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

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

人气教程排行