python - Twisted AMP - 如何发送大于 64K 的值

标签 python twisted asynchronous-messaging-protocol

我正在使用 Twisted + AMP 在服务器和客户端之间进行通信,两者都是 Python,完全在我的控制之下。我的消息通常很短,但有时一个参数可能会超过 64K 的限制。有什么办法可以优雅地处理这个问题吗?

我看到 AMPv2 可以处理长消息,但我认为 Twisted 实现适用于 AMPv1。

我怀疑分块将是答案的一部分,但我不确定该怎么做。我只有一种方法容易受到这些长消息的影响,所以我不需要最通用的解决方案。如果有帮助,我愿意创建不同的 amp.Argument 子类。

最佳答案

你可以使用下面的代码

# From lp:~glyph/+junk/amphacks
"""
An argument type for sending medium-sized strings (more than 64k, but small
enough that they still fit into memory and don't require streaming).
"""

from cStringIO import StringIO
from itertools import count

from twisted.protocols.amp import AMP, Argument, Command



CHUNK_MAX = 0xffff

class BigString(Argument):
    def fromBox(self, name, strings, objects, proto):
        value = StringIO()
        value.write(strings.get(name))
        for counter in count(2):
            chunk = strings.get("%s.%d" % (name, counter))
            if chunk is None:
                break
            value.write(chunk)
        objects[name] = value.getvalue()


    def toBox(self, name, strings, objects, proto):
        value = StringIO(objects[name])
        firstChunk = value.read(CHUNK_MAX)
        strings[name] = firstChunk
        counter = 2
        while True:
            nextChunk = value.read(CHUNK_MAX)
            if not nextChunk:
                break
            strings["%s.%d" % (name, counter)] = nextChunk
            counter += 1

class Send(Command):
    arguments = [('big', BigString())]

class Example(AMP):
    @Send.responder
    def gotBig(self, big):
        print 'Got a big input', len(big)
        f = file("OUTPUT", "wb")
        f.write(big)
        f.close()
        return {}

def main(argv):
    from twisted.internet import reactor
    from twisted.internet.protocol import Factory, ClientCreator
    if argv[1] == 'client':
        filename = argv[2]
        def connected(result):
            result.callRemote(Send, big=file(filename).read())
        ClientCreator(reactor, AMP).connectTCP("localhost", 4321).addCallback(
            connected)
        reactor.run()
    elif argv[1] == 'server':
        f = Factory()
        f.protocol = Example
        reactor.listenTCP(4321, f)
        reactor.run()
    else:
        print "Specify 'client' or 'server'."
if __name__ == '__main__':
    from sys import argv as arguments
    main(arguments)

PS:代码取自https://raw.githubusercontent.com/fusionapp/documint/8fdbaeb3aeb298afff4ba951243d03c98fe8ff99/documint/mediumbox.py

关于python - Twisted AMP - 如何发送大于 64K 的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57078561/

相关文章:

python - 有谁知道 python 的异步 mysql 库?

python - 序列化twisted.protocols.amp.AmpList以进行测试

python - 程序退出时MySQL行被删除

python - 在单个节点/服务器上使用 Twisted Threading + MapReduce?

python - 类型错误 : expected string or buffer

Python 扭曲的 Reactor 类

python - LoopingCall AMP 命令

python - 使用 csv.DictReader 创建嵌套字典

python - 安装 OpenCV 失败,因为它找不到 "skbuild"