1

我正在尝试设置一个可以处理单个客户端的会话数据的 WAMP 服务器。然而,这似乎比最初想象的更麻烦。

横梁配置:

{
  "workers": [
    {
      "type": "router",
      "realms": [
        {
          "name": "default",
          "roles": [
            {
              "name": "anonymous",
              "permissions": [
                {
                  "uri": "*",
                  "call": true,
                  "register": true
                }
              ]
            }
          ]
        }
      ],
      "transports": [
        {
          "type": "websocket",
          "endpoint": {
            "type": "tcp",
            "port": 8080
          }
        }
      ],
      "components": [
        {
          "type": "class",
          "classname": "server.Server",
          "realm": "default",
          "role": "anonymous"
        }
      ]
    }
  ]
}

服务器.py:

服务器注册两个 RPC,一个用于附加数据,一个用于返回数据字符串。数据存储为self.data,但这是存储所有会话的数据,而不是基于每个客户端、每个会话。一旦会话终止,服务器应该清理会话数据。简单地清理列表不是解决方案,因为同时客户端可以访问彼此的数据。客户端的 id 在appendRPC 中可用(如果客户端公开了自己),但是此时这似乎毫无用处。

from autobahn.twisted import wamp
from autobahn.wamp import types


class Server(wamp.ApplicationSession):
    def __init__(self, *args, **kwargs):
        wamp.ApplicationSession.__init__(self, *args, **kwargs)
        self.data = []

    def onJoin(self, details):
        def append(data, details):
            client_id = details.caller
            self.data.append(data)

        def get():
            return ''.join(self.data)

        options = types.RegisterOptions(details_arg='details')
        self.register(append, 'append', options=options)
        self.register(get, 'get')

客户端.py:

客户端连接到服务器,等待连接打开并执行 RPC。'a'客户端首先将和附加'b'到服务器的数据,然后获取并打印数据。结果应该是ab每个客户端,每个会话都应该存储数据。会话结束后,应清理数据。

import asyncio

from autobahn.asyncio import wamp
from autobahn.asyncio import websocket
from autobahn.wamp import types


class Client(wamp.ApplicationSession):
    def onOpen(self, protocol):
        protocol.session = self
        wamp.ApplicationSession.onOpen(self, protocol)


if __name__ == '__main__':
    session_factory = wamp.ApplicationSessionFactory()
    session_factory.session = Client
    transport_factory = websocket.WampWebSocketClientFactory(session_factory)

    loop = asyncio.get_event_loop()
    transport, protocol = loop.run_until_complete(
        asyncio.async(loop.create_connection(
            transport_factory, 'localhost', '8080',)))

    connected = asyncio.Event()

    @asyncio.coroutine
    def poll():
        session = getattr(protocol, 'session', None)
        if not session:
            yield from asyncio.sleep(1)
            asyncio.ensure_future(poll())
        else:
            connected.set()

    # Wait for session to open.
    asyncio.ensure_future(poll())
    loop.run_until_complete(connected.wait())

    # Client is connected, call RPCs.
    options = types.CallOptions(disclose_me=True)
    protocol.session.call('append', 'a', options=options)
    protocol.session.call('append', 'b', options=options)
    f = protocol.session.call('get', options=options)
    # Get stored data and print it.
    print(loop.run_until_complete(f))

希望有人能告诉我如何在服务器内存中存储每个客户端、每个会话的数据。

4

1 回答 1

0

我设法为此创建了一个hack。这似乎不是完美的解决方案,但它现在有效。

from autobahn.twisted import wamp
from autobahn.wamp import types
from twisted.internet.defer import inlineCallbacks


class Server(wamp.ApplicationSession):
    def __init__(self, *args, **kwargs):
        wamp.ApplicationSession.__init__(self, *args, **kwargs)    
        self.sessions = {}

    def onJoin(self, details):
        def on_client_join(details):
            client_id = details['session']
            self.sessions[client_id] = {}

        def on_client_leave(client_id):
            self.sessions.pop(client_id)

        self.subscribe(on_client_join, 'wamp.session.on_join')
        self.subscribe(on_client_leave, 'wamp.session.on_leave')

        def get_session(details):
            return self.sessions[details.caller]

        @inlineCallbacks
        def append(data, details):
            session = yield self.call('get_session', details)
            d = session.setdefault('data', [])
            d.append(data)

        @inlineCallbacks
        def get(details):
            session = yield self.call('get_session', details)
            return ''.join(session['data'])

        reg_options = types.RegisterOptions(details_arg='details')
        self.register(get_session, 'get_session')
        self.register(append, 'append', options=reg_options)
        self.register(get, 'get', options=reg_options)

当客户端连接时会话被创建(on_client_join),当客户端断开连接时会话被销毁(on_client_leave)。

服务器还需要订阅元事件的权限。配置.json:

...
"permissions": [
  {
    "uri": "*",
    "call": true,
    "register": true,
    "subscribe": true,
  }
]
....
于 2015-10-27T08:41:39.357 回答