Before going with Websockets with python, firstly we will understand what is Websockets? Websocket is a communications protocol, providing full-duplex bi-directional communication over a single TCP connection. To understand Websockets, first, we have to have a clear understanding of HTTP protocol cause both go hand in hand.
HTTP Protocol
HTTP is a protocol that allows the fetching of resources, such as HTML documents. It is the foundation of any data exchange on the Web and it is a client-server protocol, which means requests are initiated by the recipient, usually the Web browser.
HyperText Transfer Protocol is an application layer is a stateless application-level protocol where the client requests information with headers using actions like GET, POST, PUT … and server send the response back to the client and the connection is closed.
For every communication, HTTP protocol will open a connection, data exchange then the connection is closed.
If the requirement is to fetch the data continuously from the server. For example fetch the real-time data for cryptocurrency exchange, gaming application or a chat application. Then there will be multiple HTTP calls to the server.
How’s the Websocket is different from traditional HTTP protocols. Websockets uses bi-directional communication and the connection will not break until the client or server decides to terminate the connection.
The Life cycle of Websockets
Websockets Handshake
Websocket is also an application layer protocol and it is an HTTP upgrade that uses the same TCP connection over ws://
In simple terms client asks for the server that, can we make a WebSocket connection and in reply server will say, yeah buddy let’s upgrade the connection to WS
This is called the handshake and the connection is established between client and server.
Open and Persistent Connection
Once the connection is established communication happens in terms of bi-directional message communication.
Connection Closed
Once the connection is established its stays forever until the client or server wants to terminate the connection.
Enough of the theory, let’s dive into the implementation. So to have a WebSocket connection we first need to have a client and a server. For the implementation, we are using Python’s Flask Server that is a microframework.
We will be using Socket.io for the client socket library and Flask-SocketIO for the server WebSocket library for our example.
Flask-SocketIO
Let’s first install all our dependencies to run the project like flask-socketio or maybe flask if that is not installed yet. As the WebSocket can connect to n number of clients, Flask has to use some asynchronous libraries like Eventlet or Gevent. So in our case, we are installing Eventlet.
To run the project with the Eventlet thread library let’s install the Gunicorn web server or maybe you can use the UWsgi server
Now we just have to set up the flask project and initialize the flask-socketio and for more information please visit the official docs of flask-socketio
By default, the server is running on 5000 port with WebSocket. Now we just need to connect from the client to the server. Let’s make the connection using Socket.io
Socket.io
To install socket.io either you can use CDN for it or if you are using npm then just fire
And to simplify our solution we are using CDN link
So above code will connect to the localhost server on port 5000 on which we have already started our flask server with WebSocket. Now our client is connected with our server and you can check that in the web console with the statement as socket connected
And to check whether the client is connected to the server or not just add the below code.
@socket_io.on('connect')
def test_connect():
print("socket connected")
Websockets Upgrade
Now, as the client and server are connected, an HTTP upgrade happened, and the connection is made on ws://localhost:5000 with status code as 101(Switching Protocols). And now all the data exchange will happen on the same network call only. You can test that in the network tab there is a header called WS in chrome.
So let’s send some data from the client to the server over the same network without creating any new network call. To send a message from client to server you can either use send or emit method.
socket.emit('message', { 'hello': 'world' });
You can even send the data to the server with a custom event just change the first parameter to anything else. But just be sure that there should be a receiver configured on the server that is listening to that event.
With Flask-SocketIO the server needs to register handlers for these events, similarly to how routes are handled by view functions.
The following example creates a server-side event handler for an unnamed event:
@socketio.on('message')
def handle_message(message):
print('received message: ' + message)
The above example uses string messages. Another type of unnamed events use JSON data:
@socketio.on('json')
def handle_json(json):
print('received json: ' + str(json))
SocketIO event handlers defined as shown in the previous section can send reply messages to the connected client using the send()
and emit()
functions.
The following examples bounce received events back to the client that sent them:
from flask_socketio import send, emit@socketio.on('message')
def handle_message(message):
send(message)@socketio.on('json')
def handle_json(json):
send(json, json=True)@socketio.on('my event')
def handle_my_custom_event(json):
emit('my response', json)
Note how send()
and emit()
are used for unnamed and named events respectively.
Broadcasting
Another very useful feature of SocketIO is the broadcasting of messages. Flask-SocketIO supports this feature with the broadcast=True
optional argument to send()
and emit()
:
@socketio.on('my event')
def handle_my_custom_event(data):
emit('my response', data, broadcast=True)
When a message is sent with the broadcast option enabled, all clients connected to the namespace receive it, including the sender.
And to handle the messages coming from the server, we have to register a new handler for the given event on the client-side, so that client can get the message from the server.
socket.on('my event', (data) => {
console.log(data); // this will log the output that server has send to the client
});
Where to use Websockets instead of traditional HTTP calls
- Real-time applications like bitcoin exchange. Just check out the link and open the chrome dev-tools network tab you can see massive to and fro of the data happening.
2. Chat application. You can check out the Socket.io chat application that uses the WebSocket concept. Please check out the link for the chat application demo.
Conclusion
Websockets are very easy, lightweight, and super interesting when you see a lot of data flowing to and fro in a single call, without bombarding the server with too many network calls.
This was just my understanding of Websocket. I hope, it has helped you. If you want to discuss anything or anything related to tech, you can contact me here or on the Contact Page.
See you next time. Peace out ✌️
Pingback: Production-ready Websockets using Flask (Python) and Celery Worker and Javascript - Progress Story