【发布时间】:2012-10-14 23:32:51
【问题描述】:
我正在尝试了解这些新奇的“工厂”风格网络库。 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() 阻塞客户端,阻止其执行任何其他工作。
人们可能每天都希望使用此功能。我怎么理解这个?
编辑:我尝试为客户端调用“签入”功能,但这似乎会使我的服务器淹没在请求中,只是为了响应“没有报告”。此外,它增加了延迟,因为客户端仅在他们请求时才收到新数据,而不是在它实际可用时。工厂 - 反应器布局似乎没有暴露我需要存储的客户信息以便任意响应它们。
【问题讨论】:
-
Lambda 是一种无需命名即可定义函数的方法;一个匿名函数。该文档显示了它们与功能的关系; docs.python.org/reference/expressions.html#lambda 话虽如此,我认为
doMath()中使用CLientCreator的代码相当可怕。它以多种方式违反了“Python 之禅”(在交互式 Python 会话中尝试import this)。 -
@RolandSmith,您对 Twisted 示例质量的意见将通过twistedmatrix.com/trac/newticket 以文档错误报告的形式更有建设性地表达。我不会说文档是完美的,但提问者试图理解的示例的质量与问题并不真正相关。
-
@RolandSmith 这不是对 lambda 的严格准确定义,因为变量范围也有一些巧妙之处
-
@RolandSmith,谢谢
import this,我没见过。作为一个自学成才的黑客,我总是害怕以错误的方式学习东西,所以我很珍惜这样的花絮。我会仔细尝试在 lambda 上提取文档。
标签: python networking twisted multiplayer