Omegle clone in Flask + Gevent + WebSockets¶
Python ranks fairly high when it comes getting things done without too much ceremony in the programming community. I briefly had some doubts of this assertion of until I finally found Flask-Sockets. This small library makes it very natural to serve WebSockets in Flask/gevent. You can consider this blog post as an advertisement for this small but extremely useful library.
In this post, I will show how to create an extremely simple omegle POC using the Gevent/Flask/Flask-Sockets combo. The end result is that the javascript client is comparable in code size to the server. Here’s the code for the server (the client is ugly and uninteresting but you can see it in the repo):
#!/usr/bin/env python2
import gevent.monkey
gevent.monkey.patch_all()
import flask
from flask import Flask
from flask_sockets import Sockets
import gevent
import gevent.queue
from gevent import pywsgi
from geventwebsocket.handler import WebSocketHandler
app = Flask(__name__, static_url_path='')
sockets = Sockets(app)
seekers = gevent.queue.Queue()
def relay(from_, to):
"""route messges from_ -> to"""
try:
while True:
to.send(from_.receive())
except:
# Notify to about disconnection - unless to disconnected
try: to.send("Peer disconnected.")
except: pass
def session(ws1, ws2):
for ws in [ws1, ws2]:
ws.send("/Found a person. Say hello")
gevent.joinall([
gevent.spawn(relay, ws1, ws2),
gevent.spawn(relay, ws2, ws1)
])
def matcher(seekers):
while True:
gevent.spawn(session, seekers.get(), seekers.get())
gevent.spawn(matcher, seekers)
@sockets.route('/ws')
def websocket(ws):
seekers.put(ws)
ws.send("/Welcome. Seeking a partner")
while True: # hack to keep the greenlet alive
gevent.sleep(0.5)
@app.route('/')
def index():
return app.send_static_file('index.html')
if __name__ == '__main__':
pywsgi.WSGIServer(('', 8000), app, handler_class=WebSocketHandler) \
.serve_forever()
The implementation is very naive but I still wonder how well it would perform. Many further improvements are possible as well:
Limit the number of concurrent sessions
Create a pool for matchers to make sure that
seekers
empties fast enoughAllow clients to advertise names
You can see the full code here.