Проблема с витым питоном - отправка двоичных данных - PullRequest
5 голосов
/ 04 августа 2009

То, что я пытаюсь сделать, довольно просто: отправить файл с клиента на сервер. Сначала клиент отправляет информацию о файле - о его размере. Затем он отправляет фактический файл.

Это то, что я сделал до сих пор:

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", я получу их оба (в одном сообщении, а не дважды).

Кто-нибудь?

1 Ответ

8 голосов
/ 04 августа 2009

Вы установили свой сервер в режим raw с помощью setRawMode (), поэтому обратный вызов rawDataReceived вызывается с входящими данными (не lineReceived). Если вы печатаете данные, полученные в rawDataReceived, вы видите все, включая содержимое файла, но когда вы вызываете pickle для десериализации данных, они игнорируются.

Либо вы изменяете способ отправки данных на сервер (я бы предложил формат netstring), либо вы передаете содержимое внутри сериализованного объекта pickle и делаете это за один вызов.

self.sendLine(pickle.dumps({"size":filesize, 'content': contents[:20]}))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...