Étant donné qu'un dossier peut avoir plusieurs niveaux de répertoires, il doit être parcouru de manière récursive.
Cet article utilise une personnalisation simple du protocole et définit cinq commandes. La commande Head est la suivante :
Sync : identifie le début de la synchronisation du dossier
Fin : identifie la fin de la synchronisation
Fichier : identifie le fichier à transférer Nom (chemin relatif)
Dossier : Dossier indicateur (chemin relatif)
Aucun : Contenu du fichier
Chaque commande commence par CMB_BEGIN et se termine par CMB_END.
Le client doit analyser le tampon de réception, retirer les instructions une par une, puis effectuer le traitement correspondant selon le responsable de l'instruction, comme la création de dossiers, l'écriture de fichiers, etc.
Voici le code du serveur :
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()
Après que le serveur ait reçu un signal du client (dans ce code, le client peut envoyer n'importe quel contenu au serveur), le serveur Send_file_folder sera appelé pour envoyer tout le contenu du dossier serveur au client.
Les résultats d'exécution du serveur sont les suivants :
Voici le code du client :
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()
Le Le client extrait les instructions du serveur, lorsque l'instruction Sync est extraite, le répertoire sourceDir est effacé, puis synchronisé avec le dossier Serveur selon les instructions ultérieures.
Les résultats d'exécution du client sont les suivants :
Choses à noter :
Lorsque le client écrit un fichier, il doit l'ouvrir dans mode binaire, sinon des erreurs peuvent survenir lors du transfert de fichiers binaires ou provoquer une corruption de fichiers.
Après les tests, le code peut s'exécuter normalement, la synchronisation des dossiers est réussie et les fichiers texte, images et autres types de fichiers binaires peuvent être transférés normalement.
Pour plus d'articles liés au code source de transmission réseau de dossiers Python basé sur le framework Twisted, veuillez faire attention au site Web PHP chinois !