Twisted python 的问题 - 发送二进制数据

Posted

技术标签:

【中文标题】Twisted python 的问题 - 发送二进制数据【英文标题】:Problem with Twisted python - sending binary data 【发布时间】:2010-11-16 18:08:10 【问题描述】:

我要做的很简单:将文件从客户端发送到服务器。首先,客户端发送有关文件的信息——即文件的大小。然后它发送实际的文件。

这是我到目前为止所做的:

服务器.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()

客户端.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”发送,我会同时收到它们(在同一条消息中,而不是两次)。

有人吗?

【问题讨论】:

【参考方案1】:

您已使用 setRawMode() 将您的服务器设置为原始模式,因此回调 rawDataReceived 将与传入数据(而不是 lineReceived)一起调用。如果您打印在 rawDataReceived 中收到的数据,您会看到包括文件内容在内的所有内容,但是当您调用 pickle 来反序列化数据时,它会被忽略。

要么更改将数据发送到服务器的方式(我建议使用 netstring 格式),要么在 pickle 序列化对象中传递内容,然后一次调用。

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

【讨论】:

虽然有一件奇怪的事情。如果我将收到的数据写入磁盘,它总是比发送的文件多 2 个字节。文件大小无关紧要。结果将始终附加 2 个字节。知道那可能是什么吗? 你可以在这里找到文件:files.getdropbox.com/u/608462/simpleclient.pyfiles.getdropbox.com/u/608462/simpleserv.py 当然长了两个字节。您正在使用 sendLine 发送任意大的二进制数据 blob。您还将整个内容缓冲到内存中,并在收到所有内容后阻止文件 IO 的协议,然后不将服务器重置为行模式。在正确之前,您还有很多代码需要删除。 :)

以上是关于Twisted python 的问题 - 发送二进制数据的主要内容,如果未能解决你的问题,请参考以下文章

Twisted irc python bot - 缓冲消息

使用 Python Twisted 和 Autobahn 从 Matlab 通过 WebSocket 发送 JSON 数据

在Twisted,Oscar中从外部事件处理程序发送ICQ消息

从 Twisted 客户端发送到 Twisted 服务器,只有这一种方式

网络爬虫之scrapy框架详解,scrapy框架设置代理

如何将结构化数据从 Twisted 发送到 syslog?