2009-08-04 9 views
5

Ce que j'essaie de faire est assez simple: envoyer un fichier du client au serveur. Tout d'abord, le client envoie des informations sur le fichier - la taille de celui-ci. Ensuite, il envoie le fichier réel.Problème avec python Twisted - envoyer des données binaires

C'est ce que je l'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 ne sortie de l'objet désérialisé:

{'size': 183574528L}

Comment ça se fait? Qu'est-ce qui est arrivé aux 20 caractères du fichier que je voulais envoyer?

Si j'utilise les envois "hej" et "wa" à la place, je les aurai tous les deux (dans le même message, pas deux fois).

Quelqu'un?

Répondre

8

Vous avez défini votre serveur en mode brut avec setRawMode(), de sorte que le rappel rawDataReceived est appelé avec les données entrantes (pas 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 des données au serveur (je suggère le format netstring), soit vous transmettez le contenu à l'intérieur de l'objet sérialisé Pickle, et cela en un seul appel.

self.sendLine(pickle.dumps({"size":filesize, 'content': contents[:20]})) 
+0

Une chose étrange cependant. Si j'écris les données que j'ai reçues sur le disque, ce sera toujours 2 octets de plus que le fichier envoyé. Peu importe le fichier, qu'il soit grand ou petit. Le résultat sera toujours ajouté de 2 octets. Vous avez une idée de ce que cela pourrait être? – quano

+0

Vous pouvez trouver les fichiers ici: http://files.getdropbox.com/u/608462/simpleclient.py http://files.getdropbox.com/u/608462/simpleserv.py – quano

+0

Bien sûr, il s'agit de deux octets plus long. Vous utilisez sendLine pour envoyer un blob de données binaires arbitrairement grand. Vous mettez également tout le tampon dans la mémoire et bloquez le protocole pour le fichier IO après avoir tout reçu, puis ne pas réinitialiser votre serveur en mode ligne. Vous avez encore beaucoup de code à supprimer avant que ce soit correct. :) – Dustin

Questions connexes