Problem mit Twisted-Python - Senden von Binärdaten
Frage
Was ich versuche zu tun ist ziemlich einfach: eine Datei vom Client zum Server senden. Zuerst sendet der Client Informationen über die Datei - die Größe der es das ist. Dann sendet er die aktuelle Datei.
Dies ist, was ich bisher getan:
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()
Der Server wird nur dann ausgegeben, das deserialisiert Objekt:
{ 'size': 183574528L}
Wie kommt das? Was passierte die 20 Zeichen aus der Datei wollte ich senden?
Wenn Sie die „hej“ verwenden und „wa“ sendet stattdessen werde ich bekommen sie beide (in der gleichen Nachricht, nicht zweimal).
Jemand?
Lösung
Sie Ihren Server Raw-Modus mit setRawMode eingestellt haben (), so dass der Rückruf rawDataReceived wird mit den eingehenden Daten genannt (nicht lineReceived). Wenn Sie die Daten drucken Sie in rawDataReceived erhalten Sie alles, einschließlich der Dateiinhalt sehen, aber wie Sie Beize rufen die Daten deserialisieren, wird es ignoriert.
Entweder Sie ändern, wie Sie Daten an den Server senden (ich würde das netstring Format vorschlagen) oder Sie übergeben den Inhalt innerhalb der Gurke serialisiert Objekts, und tue dies in einem Aufruf.
self.sendLine(pickle.dumps({"size":filesize, 'content': contents[:20]}))