简体   繁体   English

如何使用autobahn asyncio实现交互式websocket客户端?

[英]How can I implement an interactive websocket client with autobahn asyncio?

I'm trying to implement a websocket/wamp client using autobahn|python and asyncio , and while it's somewhat working, there are parts that have eluded me. 我正在尝试使用autobahn | python和asyncio实现一个websocket / wamp客户端,尽管它有些起作用,但有些地方让我asyncio

What I'm really trying to do is implement WAMP in qt5/QML, but this seemed like an easier path for the moment. 我真正想做的是在qt5 / QML中实现WAMP,但是目前看来这是一条更简单的方法。

This simplified client mostly copied from online does work. 这种简化的客户端通常是从在线复制的,确实可以工作。 It reads the time service when the onJoin occurs. onJoin发生时,它将读取时间服务。

What I'd like to do is trigger this read from an external source. 我想做的是触发来自外部源的读取。

The convoluted approach I've taken is to run the asyncio event loop in a thread, and then to send a command over a socket to trigger the read. 我采用的复杂方法是​​在线程中运行asyncio事件循环,然后通过套接字发送命令以触发读取。 I have so far unable to figure out where to put the routine/coroutine so that it can be found from the reader routine. 到目前为止,我还无法弄清楚例程/协程的放置位置,以便可以从阅读器例程中找到它。

I suspect there's a simpler way to go about this but I haven't found it yet. 我怀疑有一个更简单的方法可以解决这个问题,但我还没有找到。 Suggestions are welcome. 欢迎提出建议。

#!/usr/bin/python3
try:
    import asyncio
except ImportError:
    ## Trollius >= 0.3 was renamed
    import trollius as asyncio

from autobahn.asyncio import wamp, websocket
import threading
import time
from socket import socketpair

rsock, wsock = socketpair()

def reader() :
    data = rsock.recv(100)
    print("Received:", data.decode())

class MyFrontendComponent(wamp.ApplicationSession):
    def onConnect(self):
        self.join(u"realm1")



    @asyncio.coroutine
    def onJoin(self, details):
        print('joined')
        ## call a remote procedure
        ##
        try:
           now = yield from self.call(u'com.timeservice.now')
        except Exception as e:
           print("Error: {}".format(e))
        else:
           print("Current time from time service: {}".format(now))



    def onLeave(self, details):
        self.disconnect()

    def onDisconnect(self):
        asyncio.get_event_loop().stop()



def start_aloop() :
    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)
    transport_factory = websocket.WampWebSocketClientFactory(session_factory,
                    debug = False,
                    debug_wamp = False)
    coro = loop.create_connection(transport_factory, '127.0.0.1', 8080)
    loop.add_reader(rsock,reader)
    loop.run_until_complete(coro)
    loop.run_forever()
    loop.close()

if __name__ == '__main__':
    session_factory = wamp.ApplicationSessionFactory()
    session_factory.session = MyFrontendComponent

    ## 4) now enter the asyncio event loop
    print('starting thread')
    thread = threading.Thread(target=start_aloop)
    thread.start()
    time.sleep(5)
    print("IN MAIN")
    # emulate an outside call
    wsock.send(b'a byte string')

You can listen on a socket asynchronous inside the event loop, using loop.sock_accept . 您可以使用loop.sock_accept事件循环内部的异步套接字。 You can just call a coroutine to setup the socket inside of onConnect or onJoin : 您可以调用协程在onConnectonJoin内部设置套接字:

try:
    import asyncio
except ImportError:
    ## Trollius >= 0.3 was renamed
    import trollius as asyncio

from autobahn.asyncio import wamp, websocket
import socket

class MyFrontendComponent(wamp.ApplicationSession):
    def onConnect(self):
        self.join(u"realm1")

    @asyncio.coroutine
    def setup_socket(self):
        # Create a non-blocking socket
        self.sock = socket.socket()
        self.sock.setblocking(0)
        self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.sock.bind(('localhost', 8889))
        self.sock.listen(5)
        loop = asyncio.get_event_loop()
        # Wait for connections to come in. When one arrives,
        # call the time service and disconnect immediately.
        while True:
            conn, address = yield from loop.sock_accept(self.sock)
            yield from self.call_timeservice()
            conn.close()

    @asyncio.coroutine
    def onJoin(self, details):
        print('joined')
        # Setup our socket server
        asyncio.async(self.setup_socket())

        ## call a remote procedure
        ##
        yield from self.call_timeservice()

    @asyncio.coroutine
    def call_timeservice(self):
        try:
           now = yield from self.call(u'com.timeservice.now')
        except Exception as e:
           print("Error: {}".format(e))
        else:
           print("Current time from time service: {}".format(now))

    ... # The rest is the same

Thanks for the response dano. 感谢您的回复。 Not quite the solution I needed but it pointed me in the right direction. 并不是我需要的解决方案,但它为我指明了正确的方向。 Yes, I wish to have the client mae remote RPC calls from an external trigger. 是的,我希望客户端可以从外部触发器进行远程RPC调用。

I came up with the following which allows me to pass a string for the specific call ( though only one is implemented right now) 我想出了以下内容,它允许我为特定的调用传递一个字符串(尽管现在仅实现了一个)

Here's what I came up with, though I'm not sure how elegant it is. 这是我想出的,尽管我不确定它有多优雅。

import asyncio
from autobahn.asyncio import wamp, websocket
import threading
import time
import socket


rsock, wsock = socket.socketpair()

class MyFrontendComponent(wamp.ApplicationSession):
    def onConnect(self):
        self.join(u"realm1")

    @asyncio.coroutine
    def setup_socket(self):
        # Create a non-blocking socket
        self.sock = rsock
        self.sock.setblocking(0)
        loop = asyncio.get_event_loop()
        # Wait for connections to come in. When one arrives,
        # call the time service and disconnect immediately.
        while True:
            rcmd = yield from loop.sock_recv(rsock,80)
            yield from self.call_service(rcmd.decode())

    @asyncio.coroutine
    def onJoin(self, details):
        # Setup our socket server
        asyncio.async(self.setup_socket())


    @asyncio.coroutine
    def call_service(self,rcmd):
        print(rcmd)
        try:
           now = yield from self.call(rcmd)
        except Exception as e:
           print("Error: {}".format(e))
        else:
           print("Current time from time service: {}".format(now))



    def onLeave(self, details):
        self.disconnect()

    def onDisconnect(self):
        asyncio.get_event_loop().stop()



def start_aloop() :
    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)
    transport_factory = websocket.WampWebSocketClientFactory(session_factory,
                    debug = False,
                    debug_wamp = False)
    coro = loop.create_connection(transport_factory, '127.0.0.1', 8080)
    loop.run_until_complete(coro)
    loop.run_forever()
    loop.close()

if __name__ == '__main__':
    session_factory = wamp.ApplicationSessionFactory()
    session_factory.session = MyFrontendComponent

    ## 4) now enter the asyncio event loop
    print('starting thread')
    thread = threading.Thread(target=start_aloop)
    thread.start()
    time.sleep(5)
    wsock.send(b'com.timeservice.now')
    time.sleep(5)
    wsock.send(b'com.timeservice.now')
    time.sleep(5)
    wsock.send(b'com.timeservice.now')

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Websocket 升级失败:403 Forbidden autobahn asyncio - Websocket upgrade failed: 403 Forbidden autobahn asyncio 如何将来自 python cmd 的输入发送到在同一解释器中运行的高速公路 websocket 客户端? - How do I send input from python cmd to autobahn websocket client running in the same interpreter? 如何在类中实现asyncio websockets? - How can I implement asyncio websockets in a class? Python3 和 asyncio:如何将 websocket 服务器实现为 asyncio 实例? - Python3 and asyncio: how to implement websocket server as asyncio instance? 如何通过使用asyncio检查Websocket数据是否为空 - How can I check the Websocket data is empty by using asyncio 如何在Windows的Python 3中仅安装Autobahn(仅用于asyncio而不是Twisted),而没有整个Crossbar程序包膨胀? - How can I install Autobahn only (for use only with asyncio rather than Twisted), without the entire Crossbar package bloat, in Python 3 on Windows? 使用Twisted / Autobahn Websockets编写“交互式”客户端 - Writing an “interactive” client with Twisted/Autobahn Websockets Python - 在一个单独的子进程或线程中运行Autobahn | Python asyncio websocket服务器 - Python - Running Autobahn|Python asyncio websocket server in a separate subprocess or thread 高速公路websocket - Autobahn websocket 我如何将纵横制客户端(python3,asyncio)与tkinter集成 - How I can integrate crossbar client (python3,asyncio) with tkinter
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM