Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Combining websockets and WSGI in a python app

I'm working on a scientific experiment where about two dozen test persons play a turn-based game with/against each other. Right now, it's a Python web app with a WSGI interface. I'd like to augment the usability with websockets: When all players have finished their turns, I'd like to notify all clients to update their status. Right now, everyone has to either wait for the turn timeout, or continually reload and wait for the "turn is still in progress" error message not to appear again (busy waiting, effectively).

I read through multiple websocket libraries' documentation and I understand how websockets work, but I'm not sure about the architecture for mixing WSGI and websockets: Can I have a websockets and a WSGI server in the same process (and if so, how, using really any websockets library) and just call my_websocket.send_message() from a WSGI handler, or should I have a separate websockets server and do some IPC? Or should I not mix them at all?

edit, 6 months later: I ended up starting a separate websockets server process (using Autobahn), instead of integrating it with the WSGI server. The reason was that it's much easier and cleaner to separate the two of them, and talking to the websockets server from the WSGI process (server to server communication) was straight forward and worked on the first attempt using websocket-client.

like image 686
Simon Avatar asked Oct 30 '12 10:10

Simon


People also ask

Does Wsgi support WebSockets?

As of version 0.9. 13, eventlet. websocket supports SSL websockets; all that's necessary is to use an SSL wsgi server. The web socket spec is still under development, and it will be necessary to change the way that this module works in response to spec changes.

Is Python good for WebSockets?

websockets is a library for building WebSocket servers and clients in Python with a focus on correctness, simplicity, robustness, and performance. Built on top of asyncio , Python's standard asynchronous I/O framework, it provides an elegant coroutine-based API.

Does flask support WebSockets?

Flask, being a minimalist web framework, does not have WebSocket support built-in. The old Flask-Sockets extension, which has not been maintained in the last few years, provided support for this protocol.


2 Answers

Here is an example that does what you want:

  • https://github.com/tavendo/AutobahnPython/tree/master/examples/twisted/websocket/echo_wsgi

It runs a WSGI web app (Flask-based in this case, but can be anything WSGI conforming) plus a WebSocket server under 1 server and 1 port.

You can send WS messages from within Web handlers. Autobahn also provides PubSub on top of WebSocket, which greatly simplifies the sending of notifications (via WampServerProtocol.dispatch) like in your case.

  • http://autobahn.ws/python

Disclosure: I am author of Autobahn and work for Tavendo.

like image 97
oberstet Avatar answered Sep 20 '22 18:09

oberstet


but I'm not sure about the architecture for mixing WSGI and websockets

I made it

use WSocket

Simple WSGI HTTP + Websocket Server, Framework, Middleware And App.

Includes

  • Server(WSGI) included - works with any WSGI framework
  • Middleware - adds Websocket support for any WSGI framework
  • Framework - simple Websocket WSGI web application framework
  • App - Event based app for Websocket communication When external server used, some clients like Firefox requires http 1.1 Server. for Middleware, Framework, App
  • Handler - adds Websocket support to wsgiref(python builtin WSGI server)
  • Client -Coming soon...

Common Features

  • only single file less than 1000 lines
  • websocket sub protocol supported
  • websocket message compression supported (works if client asks)
  • receive and send pong and ping messages(with automatic pong sender)
  • receive and send binary or text messages
  • works for messages with or without mask
  • closing messages supported
  • auto and manual close

example using bottle web framework and WSocket middleware

from bottle import request, Bottle
from wsocket import WSocketApp, WebSocketError, logger, run
from time import sleep

logger.setLevel(10)  # for debugging

bottle = Bottle()
app = WSocketApp(bottle)
# app = WSocketApp(bottle, "WAMP")

@bottle.route("/")
def handle_websocket():
    wsock = request.environ.get("wsgi.websocket")
    if not wsock:
        return "Hello World!"

    while True:
        try:
            message = wsock.receive()
            if message != None:
                print("participator : " + message)
                
            wsock.send("you : "+message)
            sleep(2)
            wsock.send("you : "+message)
            
        except WebSocketError:
            break
            
run(app)
like image 41
Kavindu Santhusa Avatar answered Sep 21 '22 18:09

Kavindu Santhusa