2009-08-04 15 views
5

私がやっていることは、かなりシンプルです。クライアントからサーバーにファイルを送信します。まず、クライアントはファイルに関する情報を送信します。次に、実際のファイルを送信します。 Twisted pythonの問題 - バイナリデータの送信

この

は、私がこれまで何をやったかである:

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"を使うと、私はそれらを両方(同じメッセージの中で2回ではなく)取得します。

誰か?

答えて

8

setRawMode()を使用してサーバーをrawモードに設定しているため、受信データ(lineReceivedではなく)でコールバックrawDataReceivedが呼び出されています。 rawDataReceivedで受け取ったデータを印刷すると、ファイルの内容を含むすべてが表示されますが、データを逆シリアル化するためにpickleを呼び出すと、無視されます。

サーバーにデータを送信する方法(ネットストリング形式を提案する)を変更するか、コンテンツをpickleシリアル化オブジェクト内に渡して、これを1回の呼び出しで行うかのどちらかです。

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

奇妙なものですが。受信したデータをディスクに書き込むと、送信されたファイルよりも常に2バイト多くなります。それはどんなに大きくても小さくても問題ありません。結果には常に2バイトが付加されます。それが何であるかの手がかりを得ましたか? – quano

+0

ここにファイルがあります: http://files.getdropbox.com/u/608462/simpleclient.py http://files.getdropbox.com/u/608462/simpleserv.py – quano

+0

もちろん2バイトですより長いです。あなたはsendLineを使用して、任意の大きさのバイナリデータブロブを送信しています。サーバー全体をメモリにバッファリングし、ファイルIOのプロトコルをブロックした後、サーバーをラインモードにリセットしません。これが正しい前に、まだ多くのコードを削除する必要があります。 :) – Dustin

関連する問題