Create an application with websockets and flask

Step 1: Clone the empty flask application

We are going to use an initial flask project.

If you want to know more we recommend to do the API REST tutorial with flask.

Another requirement for this tutorial is knowledge of pyenv and virtualenv. You could opt to use virtualenvwrapper.

In this tutorial we are going to use Flask-SocketIO.

For this tutorial some Python and Javascript knowledge is required. We will try to explain how to use websocket on both sides, the client and in the backend.

Clone our repository:

pyenv virtualenv 3.6.0 websockets
pyenv activate websockets
git clone https://github.com/tutorialstechnology/flask_websockets.git
pip install -r requirements.txt

Flask-SocketIO is compatible with both Python 2.7 and Python 3.3+, in this tutorial we are going to use Python 3.

Now that we have out empty flask application we are ready to add Flask-SocketIO.

Step 2: Adding Flask-SocketIO to flask

Open the file app.py from the repository and change it with the following content: You can check the branch final on the git repository for viewing the final code of this tutorial. We recommend to first try to follow it before going to the final code.

# -*- coding: utf-8 -*-
from flask import Flask
from flask_socketio import SocketIO

app = Flask(__name__)
socketio = SocketIO(app)

from views import index

Note that we are going to use SocketIO instance later. This new object will be used for register websockets handlers.

Now we need to provide static files for using socketio.js Open the file temples/index.html and replace with this content:

<!doctype html>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/socket.io/1.3.6/socket.io.min.js"></script>
<title>Websockets tutorial</title>
<link rel=stylesheet type=text/css href="{{ url_for('static', filename='style.css') }}">
<div class=page>
    <h1>Hello World!</h1>
</div>

Step 3: Adding the client code

Now we are going to create a new file called app.js where we will write the socketio client code. Create a new file in the static directory called app.js with the following content:

var socket = io.connect('http://' + document.domain + ':' + location.port);
socket.on('connect', function() {
    // we emit a connected message to let knwo the client that we are connected.
    socket.emit('client_connected', {data: 'New client!'});
});

Add to the templates/index.html the app.js file:

<script type="text/javascript" src="{{ url_for('static', filename='app.js') }}"></script>

You can add it just before the styles.css.

Step 4: Backend code to support socketio messages

Flask-SocketIO uses decorators to receive message. You can also use the on_event method alternative.

Create a new file called websockets.py and paste this code:

from flask_socketio import send, emit


@socketio.on('client_connected')
def handle_client_connect_event(json):
    print('received json: {0}'.format(str(json)))

In order to our flask app to recognize the new websockets handlers we need to include them on the app.py. Open the app.py and add the following import at the end of the file (you can use bluprints to avoid doing this import and break PEP8).

from websockets import (
      handle_client_connect_event,
)

Execute the run.sh file to start the flask server.

Now open the browser at http://localhost:5000 and check the output of the run.sh. You should see something like this output:

192.168.45.158 - - [16/May/2017 21:43:39] "GET /socket.io/?EIO=3&transport=polling&t=1495134962706-0 HTTP/1.1" 200 -
received json: {'data': 'New client!'}
192.168.45.158 - - [16/May/2017 21:43:39] "POST /socket.io/?EIO=3&transport=polling&t=1495134962740-1&sid=b1a5062f71954048948cddd44242fdb0 HTTP/1.1" 200 -
192.168.45.158 - - [16/May/2017 21:43:39] "GET /favicon.ico HTTP/1.1" 404 -
192.168.45.158 - - [16/May/2017 21:43:47] "GET / HTTP/1.1" 200 -
192.168.45.158 - - [16/May/2017 21:43:47] "GET /static/style.css HTTP/1.1" 200 -
192.168.45.158 - - [16/May/2017 21:43:47] "GET /static/app.js HTTP/1.1" 200 -
192.168.45.158 - - [16/May/2017 21:43:47] "GET /socket.io/?EIO=3&transport=polling&t=1495134970587-0 HTTP/1.1" 200 -
192.168.45.158 - - [16/May/2017 21:43:47] "GET /favicon.ico HTTP/1.1" 404 -
received json: {'data': 'New client!'}
192.168.45.158 - - [16/May/2017 21:43:47] "POST /socket.io/?EIO=3&transport=polling&t=1495134970621-1&sid=2fa9854e4647492b8b4de0bd0fdbd59b HTTP/1.1" 200 -

Step 5: Using Send and Emit on websockets (client and backend)

You can send reply messages to connected clients with send() and emit() functions. Here is a brief description of each function: emit: allows you to emit custom events on the server and client. send: sends messages which are received with the 'message' event.

Open the websockets.py and add the following handlers:

@socketio.on('message')
def handle_json_button(json):
    # it will forward the json to all clients.
    send(json, json=True)


@socketio.on('alert_button')
def handle_alert_event(json):
    # it will forward the json to all clients.
    print('Message from client was {0}'.format(json))
    emit('alert', 'Message from backend')

On the client side add support for the new events. Add this javascript code at the end of the app.js file:


socket.on('message', function (data) {
    console.log('message form backend ' + data);
});

socket.on('alert', function (data) {
    alert('Alert Message!! ' + data);
});

function json_button() {
    socket.send('json_button', '{"message": "test"}');
}

function alert_button() {
    socket.send('alert_button', 'Message from client!!')
}

Finally add the buttons in the html:

<button onclick="json_button()">Json Message</button>
<button onclick="alert_button()">Alert Message</button>

Now you are ready to use the websockets application!