【问题标题】:Why cant I use gevent websockets inside a greenlet为什么我不能在 greenlet 中使用 gevent websockets
【发布时间】:2019-04-10 14:49:30
【问题描述】:

我正在尝试在 greenlet 中接收 websocket 消息,但它似乎没有工作。我有这个代码:

import gevent
from geventwebsocket.handler import WebSocketHandler
from gevent.pywsgi import WSGIServer
from geventwebsocket import WebSocketServer, WebSocketApplication, Resource



def recvWs(ws):
    gevent.sleep(0)
    recvedData = ws.receive()
    rData = json.loads(recvedData)
    print(rData)

def app(environ, start_response):


    websocket = environ['wsgi.websocket']

    while True:
        gevent.spawn(recvWs,websocket)
        gevent.sleep(0)

if __name__ == '__main__':
    server = WSGIServer(("0.0.0.0", 80), app,handler_class=WebSocketHandler)
    server.serve_forever()

并且运行时返回这个错误:

<Greenlet "Greenlet-0" at 0x23fa4306148: 
recvWs(<geventwebsocket.websocket.WebSocket object at 0x0)> failed with 
RuntimeError

还有:

line 197, in read_frame
header = Header.decode_header(self.stream)

我该如何解决这个问题?

【问题讨论】:

  • 你把事情复杂化了。每个到 web 服务的连接都是它自己的异步线程。如果您通过 Web 连接生成新的 greenlet,则没有与该功能的连接,因此无法获取数据。您的代码中也没有 JSON 导入,所以不确定它是否会起作用。
  • @eatmeimadanish,我怎样才能轻松地从我的主代码中修改 websocket 对象/线程? “如果您通过网络连接生成新的greenlet,则与该功能没有连接,因此无法获取数据”,我不明白,您能详细说明吗?

标签: python websocket gevent greenlets


【解决方案1】:

这是我所做的一个很好的例子。
Python 与瓶子和 gevent:

from gevent import sleep as gsleep, Timeout
from geventwebsocket import WebSocketError
from bottle import Bottle, get, post, route, request, response, template, redirect, abort

@route('/ws/app')
def handle_websocket():
    wsock = request.environ.get('wsgi.websocket')
    if not wsock:
        abort(400, 'Expected WebSocket request.')
    # Send initial data here
    wsock.send(json.dumps(data))
    while 1:
        try:
            #Process incoming message.  2 second timeout to not block
            message = {}
            with Timeout(2, False) as timeout:
                message = wsock.receive()
            if message:
                message = json.loads(message)
                if isinstance(message, dict):
                     # Do something with data and return
                     wsock.send(json.dumps(result))
            # Add an additional second just for sanity.  Not necessarily needed
            gsleep(1)
        except WebSocketError:
            break
        except Exception as exc:
            traceback.print_exc()
            gsleep(2)

然后在您的 javascript 中打开一个 websocket 连接并像往常一样发送和接收数据。

【讨论】:

  • 如果我错了,请纠正我,但超时给了 websocket 2 秒的响应时间?如果是这样,我怎样才能让 websockets 在单独的线程中接收? (我的目标是让 websocket 消息以一致的时间间隔发送)
  • 所以超时是为了让 websocket 不会永远阻塞等待输入。如果你把它拿出来,循环将永远不会继续,因为 wsock.recieve() 永远不会结束。我不喜欢这种设计,因为我可能希望应用程序查找循环之外的更新数据。这不会影响向客户端发送数据。
  • 路由也自动被视为独立于主请求的线程。
  • 所以基本上如果我超时它不会阻塞并且不会影响发送更新的频率(如果它们在同一个循环中)?
  • 是的,如果您摆脱 gsleep(1),它将实时响应您的消息。
猜你喜欢
  • 1970-01-01
  • 2013-06-20
  • 1970-01-01
  • 2021-03-04
  • 1970-01-01
  • 2012-12-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多