我正在尝试设置一个可以处理各个客户端的会话数据的WAMP服务器。然而,这似乎比最初的想法更麻烦。
Crossbar配置:
{
"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"
}
]
}
]
}
server.py:
服务器注册两个RPC,一个用于附加数据,一个用于返回数据字符串。数据存储为self.data
,但这是为每个会话存储所有会话的数据,而不是每个客户端的数据。会话终止后,服务器应清理会话数据。简单地清理列表不是解决方案,因为同时客户端可以访问彼此的数据。
客户端的id在append
RPC中可用(如果客户端公开了自己),但是此时这似乎没用。
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')
client.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))
希望有人能告诉我如何在服务器内存中按会话存储每个客户端的数据。
答案 0 :(得分: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
)时会话被破坏。
服务器还需要权限才能订阅元事件。 config.json:
...
"permissions": [
{
"uri": "*",
"call": true,
"register": true,
"subscribe": true,
}
]
....