我试图了解如何找出如何让服务器知道哪个客户端在twisted的透视代理中发出远程请求。我想我应该使用twisted.spread.pb.Viewable
,但是当我尝试Viewable的view_*
方法中的perspective参数是None时。
我运行此服务器
import twisted.spread.pb as pb
import twisted.internet.reactor as reactor
class Server(pb.Root):
def __init__(self):
self.v = MyViewable()
def remote_getViewable(self):
return self.v
class MyViewable(pb.Viewable):
def view_foo(self, perspective):
print ("Perspective %s"%perspective)
if __name__ == "__main__":
reactor.listenTCP(54321, pb.PBServerFactory(Server()))
print("Starting reactor")
reactor.run()
和这个客户
import twisted.spread.pb as pb
import twisted.internet.reactor as reactor
from twisted.internet.defer import inlineCallbacks
@inlineCallbacks
def gotRoot(root):
v1 = yield root.callRemote("getViewable")
v2 = yield root.callRemote("getViewable")
print(v1)
print(v2)
yield v1.callRemote("foo")
yield v2.callRemote("foo")
factory = pb.PBClientFactory()
reactor.connectTCP("localhost", 54321, factory)
d = factory.getRootObject()
d.addCallback(gotRoot)
reactor.run()
服务器的输出是
Starting reactor
Perspective None
Perspective None
为什么透视参数为None?
答案 0 :(得分:0)
通过实验,我相信我已经确定了答案。
为了在pb.Viewable上远程调用view_ *方法以正确接收透视参数,必须获取客户端持有的Viewable的引用作为来自于调用的perspective_ *方法的返回值。 pb.Avatar(或子类)的实例。传递给view_ *方法的透视参数然后对应于最初为客户端提供对Viewable的引用的头像。
原始发布中的示例代码无法正常工作,因为对Viewable的远程引用从pb.Root传递到客户端,而不是作为pb.Avatar上的perspective_ *方法的返回值。
我在这里注意到虽然examples in the official documents的编写方式暗示了这些信息,但似乎没有明确说明。
编辑:我已经找到正确的方式来执行此操作。 Realm的requstAvatar
方法的一个参数是用户的mind
。您所要做的就是将mind.perspective
设置为新的Avatar实例,并且所有后续远程调用都会按照您的预期运行。例如:
class SimpleRealm:
implements(IRealm)
def requestAvatar(self, avatarId, mind, *interfaces):
avatar = MyAvatarSubclass()
mind.perspective = avatar
return pb.IPerspective, avatar, avatar.logout
OLD EDIT :实现此工作的一种(糟糕的)方法是显式构造pb.ViewPoint
并将其作为参数传递给远程客户端。例如,如果p
是Avatar子类的实例,而v
是可在服务器端查看的,我们可以在服务器上执行此操作
referenceToClient.callRemote("take", ViewPoint(p, v))
在客户端,我们有类似
的东西def remote_take(self, objToReceive):
self.myView = objToReceive
客户端对self.myView.callRemote(...)
的后续调用将正常工作