Question

Ce que j'essaie de faire est assez simple: envoyer un fichier de client à serveur. Tout d’abord, le client envoie des informations sur le fichier - sa taille. Ensuite, il envoie le fichier réel.

C’est ce que j’ai fait jusqu’à présent:

Server.py

from twisted.internet import reactor, protocol
from twisted.protocols.basic import LineReceiver

import pickle
import sys

class Echo(LineReceiver):

    def connectionMade(self):
        self.factory.clients.append(self)
        self.setRawMode()

    def connectionLost(self, reason):
        self.factory.clients.remove(self)

    def lineReceived(self, data):
        print "line", data

    def rawDataReceived(self, data):
            try:
                obj = pickle.loads(data)
                print obj
            except:
                print data

        #self.transport.write("wa2")

def main():
    """This runs the protocol on port 8000"""
    factory = protocol.ServerFactory()
    factory.protocol = Echo
    factory.clients = []
    reactor.listenTCP(8000,factory)
    reactor.run()

# this only runs if the module was *not* imported
if __name__ == '__main__':
    main()

Client.py

import pickle

from twisted.internet import reactor, protocol
import time
import os.path
from twisted.protocols.basic import LineReceiver

class EchoClient(LineReceiver):

    def connectionMade(self):
        file = "some file that is a couple of megs"
        filesize = os.path.getsize(file)
        self.sendLine(pickle.dumps({"size":filesize}))

        f = open(file, "rb")
        contents = f.read()
        print contents[:20]
        self.sendLine(contents[:20])
        f.close()

#        self.sendLine("hej")
#        self.sendLine("wa")

    def connectionLost(self, reason):
        print "connection lost"

class EchoFactory(protocol.ClientFactory):
    protocol = EchoClient

    def clientConnectionFailed(self, connector, reason):
        print "Connection failed - goodbye!"
        reactor.stop()

    def clientConnectionLost(self, connector, reason):
        print "Connection lost - goodbye!"
        reactor.stop()


# this connects the protocol to a server runing on port 8000
def main():
    f = EchoFactory()
    reactor.connectTCP("localhost", 8000, f)
    reactor.run()

# this only runs if the module was *not* imported
if __name__ == '__main__':
    main()

Le serveur produira uniquement l'objet désérialisé:

{'taille': 183574528L}

Comment ça se fait? Qu'advient-il des 20 caractères du fichier que je voulais envoyer?

Si vous utilisez les " hej " et " wa " envoie à la place, je les aurai tous les deux (dans le même message, pas deux fois).

Quelqu'un?

Était-ce utile?

La solution

Vous avez défini votre serveur en mode brut avec setRawMode (). Le rappel rawDataReceived est donc appelé avec les données entrantes (et non par lineReceived). Si vous imprimez les données que vous recevez dans rawDataReceived, vous voyez tout, y compris le contenu du fichier, mais lorsque vous appelez pickle pour désérialiser les données, elles sont ignorées.

Soit vous modifiez la manière dont vous envoyez les données au serveur (je suggérerais le format netstring), soit vous transmettez le contenu à l'intérieur de l'objet sérialisé pickle et vous le faites en un seul appel.

self.sendLine(pickle.dumps({"size":filesize, 'content': contents[:20]}))
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top