1

我试图了解如何让服务器知道在扭曲的透视代理中哪个客户端正在发出远程请求。我想我应该使用twisted.spread.pb.Viewable这个,但是当我尝试 Viewableview_*方法中的透视参数是 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

为什么透视参数没有?

4

1 回答 1

0

通过实验,我相信我已经确定了答案。

为了在 pb.Viewable 上远程调用 view_* 方法以正确接收透视参数,必须已从在 pb 实例上调用的 perspective_* 方法中获得对客户端持有的 Viewable 的引用作为返回值.Avatar(或子类)。传递给 view_* 方法的透视参数然后对应于最初为客户端提供对 Viewable 的引用的 Avatar。

原始帖子中的示例代码无法正常工作,因为对 Viewable 的远程引用是从 pb.Root 传递给客户端的,而不是作为 pb.Avatar 上的 perspective_* 方法的返回值。

我在这里注意到,虽然官方文档中示例的编写方式暗示了这些信息,但似乎并没有明确说明。

编辑:我已经找到了正确的方法来做到这一点。RealmrequstAvatar方法的参数之一是用户的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

旧编辑:使这项工作的一种(糟糕的)方法是显式构造 apb.ViewPoint并将其作为参数传递给远程客户端。例如,如果p是 Avatar 子类的实例并且v在服务器端是可查看的,我们可以在服务器上执行此操作

referenceToClient.callRemote("take", ViewPoint(p, v))

在客户端我们有类似的东西

def remote_take(self, objToReceive):
    self.myView = objToReceive

客户端的后续调用self.myView.callRemote(...)将正常工作

于 2013-11-20T01:40:42.627 回答