2009-08-04 115 views
5

我試圖做的是相當簡單:從客戶端發送文件到服務器。首先,客戶端發送有關文件的信息 - 它的大小。然後它發送實際的文件。問題與扭曲的蟒蛇 - 發送二進制數據

這是我迄今所做的:

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」和「WA」發送相反,我會得到他們兩個(在相同的消息,而不是兩次)。

有人?

回答

8

您已經設置了服務器的原始模式setRawMode(),所以回調rawDataReceived被稱爲與輸入數據(不lineReceived)。如果您打印您在rawDataReceived中收到的數據,則會看到包括文件內容在內的所有內容,但當您調用pickle來反序列化數據時,它將被忽略。

要麼你改變你發送數據到服務器的方式(我會建議netstring格式),或者你將內容傳遞給pickle序列化對象,並在一次調用中完成。

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

雖然一個奇怪的事情。如果我將收到的數據寫入磁盤,它將比發送的文件總是多2個字節。無論文件大小如何,都無關緊要。結果將始終附加2個字節。有什麼線索可能是什麼? – quano 2009-08-05 00:49:21