مشكلة مع الثعبان الملتوية - إرسال البيانات الثنائية
سؤال
ما أحاول القيام به هو بسيط نسبيا: إرسال ملف من العميل إلى الملقم. أولا، يرسل العميل معلومات حول الملف - حجم منه وهذا هو. ثم يرسل الملف الفعلي.
وهذا ما قمت به حتى الآن:
و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()
والخادم سوف إخراج الكائن إلغاء تسلسل فقط:
{ 'حجم': 183574528L}
وكيف يحدث ذلك؟ ما حدث إلى 20 حرف من ملف أردت أن ترسل؟
إذا استخدم "HEJ" و "وا" يرسل بدلا من ذلك، سوف تحصل لهم على حد سواء (في نفس الرسالة، وليس مرتين).
وشخص ما؟
المحلول
ولقد وضع الملقم الخاص بك لوضع raw مع setRawMode ()، لذلك يطلق على هذا الاستدعاء rawDataReceived مع البيانات الواردة (لا lineReceived). إذا قمت بطباعة البيانات التي تتلقاها في rawDataReceived، ترى كل شيء بما في ذلك محتوى الملف، ولكن كما تسمونه المخلل إلغاء تسلسل البيانات، يجري تجاهله.
وإما أن تغير الطريقة التي ترسل البيانات إلى الخادم (أود أن أقترح على شكل netstring) أو يمكنك تمرير المحتوى داخل الكائن المخلل تسلسل، والقيام بذلك في مكالمة واحدة.
self.sendLine(pickle.dumps({"size":filesize, 'content': contents[:20]}))