How to create a WebSocket in Python?

Aryan Arabshahi
July 23, 2021
Share:

WebSocket is a communications protocol, providing two-way interactive communication sessions between a client and the server. With WebSocket, you can send and receive event-driven messages. In this tutorial, we're going to create a socket server using SocketIO to build a simple chat application. SocketIO is a standard library implemented in multiple languages such as Python, JavaScript, Java and etc, which helps us to do that in an easy way. Actually, SocketIO is NOT a WebSocket implementation. Although it indeed uses WebSocket as transport when possible. You can consider the SocketIO as a slight wrapper around the WebSocket API. So, let's start:

The first step to create a chat application is to create a socket server. First of all, get the simple chat app repository using the command below:

git clone https://github.com/aryan-arabshahi/code-with-coffee-samples.git
cd ./code-with-coffee-samples/simple_chat

If you want to run the application to see how it looks, use:

pip install .
simple-chat

Note that if you are running it on another machine (VM or a remote server), you must make a build of the react project with the remote IP which is set in the config.json file.

let's have a look into the project structure:

simple_chat
│
├── MANIFEST.in
├── README
├── requirements.txt
├── setup.py
│
└── simple_chat
    │
    ├── app.py
    ├── socketio.py
    ├── enums.py
    ├── globals.py
    ├── __init__.py
    │
    ├── cli
    │   ├── __init__.py
    │   └── main.py
    │
    └── react_app
        └── build

 

There is a pre-build react application that is serving by Flask. To do that, we have the MANIFEST.in file that defines the included directories:

recursive-include simple_chat/react_app/build *

 

The "main.py" is the entry point of the project which is using the “app.py” to start the socket server:

from simple_chat.app import ChatApp


def main():
    chat_app = ChatApp()
    chat_app.start()


if __name__ == '__main__':
    main()

 

The flask_app variable is defined in the “globals.py” and the react build folder has been used for the static and the template paths:

from flask import Flask
from flask_cors import CORS


flask_app = Flask(__name__, static_folder='react_app/build/static', template_folder='react_app/build')
CORS(flask_app)

 

In this way, The Flask app can serve the react project too, but before that, we must define a route to return the index.html which is in the app.py:

from flask import render_template
from .globals import flask_app
from .socketio import socketio


@flask_app.route('/')
def index():
    return render_template('index.html')


class ChatApp:

    def start(self) -> None:
        """Run the flask app
        """
        socketio.run(
            app=flask_app,
            host='0.0.0.0',
            debug=False,
            port=5000
        )

 

And finally, we defined the socket events in the socketio.py:

from flask import request
from flask_socketio import SocketIO
from .globals import flask_app
from .enums import Sender


socketio = SocketIO(flask_app, cors_allowed_origins='*')


@socketio.on('send_message')
def send_message_handler(message: str):
    """Receive the sent messages

    Arguments:
        message {str}
    """
    socketio.emit('receive_message', {
        'sender': Sender.OTHERS.value,
        'message': f'Server: {message}',
    }, to=request.sid)

 

As you see, there is only the "send_message" event which sends back the client message to himself/herself again.

Now, it turns to create the React application which is talked about in the following link: How to create a chat application in React