2009-08-04 6 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() 

를 서버 것입니다 직렬화 복원 된 객체 만 출력 :

{ 'size': 183574528L}

어째서? 내가 보내려했던 파일에서 20 자까지 어떻게 됐어?

"hej"와 "wa"를 대신 사용하면 두 메시지가 모두 같은 메시지에 표시됩니다.

누군가?

답변

8

당신은 setRawMode()와 함께 원시 모드로 서버를 설정 한, 그래서 콜백 rawDataReceived가 들어오는 데이터 호출되고 (lineReceived되지 않음). rawDataReceived에서받은 데이터를 인쇄하면 파일 내용을 포함한 모든 내용을 볼 수 있지만 데이터를 deserialize하기 위해 pickle을 호출하면 무시됩니다.

가 어느 당신이 서버에 데이터를 전송하는 방법을 변경 (나는 netstring 형식을 건의 할 것입니다)하거나 피클 직렬화 된 객체 내부의 내용을 통과 한 통화에서이 작업을 수행.

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