python - Twisted/Amp 网络 : Respond to all clients, 不仅仅是一个发出请求的人

标签 python networking twisted multiplayer

我正在尝试学习这些新奇的“工厂”风格网络库的方法。 Twisted 广受好评,但对我来说绝对是一场噩梦,因为我不熟悉 lambda,因此我真的不确定如何遵循演示代码的功能。

演示客户端:

from twisted.internet import reactor, defer
from twisted.internet.protocol import ClientCreator
from twisted.protocols import amp
from ampserver import Sum, Divide


def doMath():
    d1 = ClientCreator(reactor, amp.AMP).connectTCP(
        '127.0.0.1', 1234).addCallback(
            lambda p: p.callRemote(Sum, a=13, b=81)).addCallback(
                lambda result: result['total'])
    def trapZero(result):
        result.trap(ZeroDivisionError)
        print "Divided by zero: returning INF"
        return 1e1000
    d2 = ClientCreator(reactor, amp.AMP).connectTCP(
        '127.0.0.1', 1234).addCallback(
            lambda p: p.callRemote(Divide, numerator=1234,
                                   denominator=0)).addErrback(trapZero)
    def done(result):
        print 'Done with math:', result
    defer.DeferredList([d1, d2]).addCallback(done)

if __name__ == '__main__':
    doMath()
    reactor.run()

演示服务器:

from twisted.protocols import amp

class Sum(amp.Command):
    arguments = [('a', amp.Integer()),
                 ('b', amp.Integer())]
    response = [('total', amp.Integer())]


class Divide(amp.Command):
    arguments = [('numerator', amp.Integer()),
                 ('denominator', amp.Integer())]
    response = [('result', amp.Float())]
    errors = {ZeroDivisionError: 'ZERO_DIVISION'}


class Math(amp.AMP):
    def sum(self, a, b):
        total = a + b
        print 'Did a sum: %d + %d = %d' % (a, b, total)
        return {'total': total}
    Sum.responder(sum)

    def divide(self, numerator, denominator):
        result = float(numerator) / denominator
        print 'Divided: %d / %d = %f' % (numerator, denominator, result)
        return {'result': result}
    Divide.responder(divide)


def main():
    from twisted.internet import reactor
    from twisted.internet.protocol import Factory
    pf = Factory()
    pf.protocol = Math
    reactor.listenTCP(1234, pf)
    print 'started'
    reactor.run()

if __name__ == '__main__':
    main()

据我了解,客户端 p.callRemote(Sum, a=13, b=81)p.callRemote(Divide, numerator=1234, denominator=0) 部分调用 Math.sum(13, 81)Math.Divide(1234, 0),因为工厂对象的 protocol 是设置为 Math 类。不知何故,当客户端收到服务器的返回值时,子函数 Done(result) 被调用,它将内容打印到屏幕上。

这很棒,但我的理解力很差,每一篇文档似乎都已经期望达到这种水平的理解。

我真正想要做的是将数据从客户端发送到服务器,以及从服务器发送到连接的多个客户端。一旦交换结束,此方法似乎就会忘记客户端,并且 reactor.run() 会阻止客户端执行任何其他工作。

人们可能每天都希望有这个功能。我该如何理解这一点?

编辑:我尝试为客户端调用“ checkin ”功能,但这似乎会使我的服务器淹没在仅响应“无报告”的请求中。此外,它还增加了延迟,因为客户端仅在请求时才收到新数据,而不是在数据实际可用时才收到。工厂 - react 器布局似乎没有公开我需要存储的客户端信息,以便任意响应它们。

最佳答案

您似乎有三个问题:

  1. lambda 在 Python 中意味着什么?”

    这是 covered by Python's documentation 。如果您仍然很难阅读以这种方式编写的代码,您可以使用lambda x: y这一事实。只是写def my_function(x): return y的捷径。无论您在哪里看到 lambda ,例如:

    def foo(bar):
        return boz().addCallback(lambda result: qux(bar, result))
    

    您随时可以拿出lambda到它自己的函数中,以便您更容易阅读,如下所示:

    def foo(bar):
        def callback_for_boz(result):
            return qux(bar, result)
        return boz().addCallback(callback_for_boz)
    
  2. "How do I make input on one connection result in output on another? "

    这是 documented by Twisted's FAQ

  3. "How do I make Twisted talk to multiple clients / connect to multiple servers? "

    这是 also a twisted FAQ 。这里的总体思路是 reactor.run()意思是“...然后运行整个程序”。您在 reactor.run() 之前运行任何代码的唯一原因是设置您的初始计时器,或监听套接字,或您的第一个连接。您可以调用connectTCPlistenTCP任意多次,无论是在运行 react 器之前还是在程序稍后发生的任何回调中。

关于python - Twisted/Amp 网络 : Respond to all clients, 不仅仅是一个发出请求的人,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13057483/

相关文章:

python - cython prange 获取 pyeval_savethread : null tstate 错误

python - 有效地将字典映射为新列

linux - 有什么方法可以区分具有相同 MAC 地址的两台 Linux 机器吗?

python 扭曲的简单客户端-服务器通信

python - 如何减少 Twisted 服务器的内存使用量?

networking - 在应用程序中一起使用 pyglet、twisted、pygtk

python - 从特征点检测返回图像中的匹配值

python - 你能在pycharm中查看hdf5文件吗?

linux - 获取打开的连接数

networking - 是否可以在 Windows 20H2 (WSL2.0) 中外部设置 "WSL"虚拟交换机以及如何配置它?