Python Flask
WebSocket Socket.IO
▌Introduction
We will use Flask-SocketIO on Flask (Server-side) and Socket.IO JS on client to establish WebSocket between them.
▌Environment
▋Python 3.6.5
▋Flask 1.0.2
▋Flask-SocketIO 3.1.2
▋Socket.IO 2.2.0
▌Implement (Server-side)
▋Install Flask-SocketIO, eventlet
$ pip install flask-socketio
$ pip install eventlet
PS. eventlet
supports good performance long-polling and WebSocket transports.
▋Receive message
Lets create two server-side event handlers:
1.
connected_event
2.
broadcast_event
The first event will be emitted and send a message
to the original client when the WebSocket connection between server and the client
is established.
The second event is used for broadcasting message to all connected clients with setting broadcast=True.
Inside the two above events, they will both emits
the client-side’s server_response
event with some data (messages).
▋main.py
from flask import Flask,
request
from flask_socketio import SocketIO,
emit
app = Flask(__name__)
# Websocket setting
app.config['SECRET_KEY'] = 'XXXXX'
socketio = SocketIO(app)
@socketio.on('connected_event')
def connected(msg):
emit('server_response', {'data': msg['data']})
@socketio.on('broadcast_event')
def broadcast(msg):
emit('server_response', {'data': msg['data']},
broadcast=True)
if __name__=='__main__':
socketio.run(app)
▋Create a web page
.
Now we are going to create index.html in Flask to interact with the server-side’s events.
The project files’ hierarchy is as following,
We will implement the template: index.html, later.
Now, update main.py
to create a new api: index, which
will render the template and return the HTML.
▋main.py
from flask import Flask, render_template, request,
jsonify
from flask_socketio import SocketIO,
emit
import json
app = Flask(__name__, template_folder='./templates')
# Websocket setting
app.config['SECRET_KEY'] = 'XXXX'
socketio = SocketIO(app)
@app.route('/')
def index():
return render_template('index.html', async_mode=socketio.async_mode)
# … Skip connected/broadcast SocketIO events
▋(Optional) Create a web api to emit client-side event
We can implement an web api to emit the event of client-side
as following codes.
@app.route('/send', methods=['POST'])
def send():
jsonobj_content
= request.json
socketio.emit('server_response', {'data':str(jsonobj_content)},
broadcast=True)
return '', 200
Notice that use socket.emit()
instead of emit()
inside a Flask api.
(Request sample in Postman)
▌Implement (Client-side)
The following steps will be implemented on index.html.
▋Install/Embed jquery, Socket.IO
For npm users,
$ npm install jquery
$ npm install socket.io-client
I will just use CDN in
my sample codes
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/socket.io/1.3.6/socket.io.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" />
▋Create connection
$(document).ready(function () {
var socket =
io.connect(); //Or given server url:
io.connect("http://xxxx:123")
});
▋Register event handlers on “connect”
See Event:Connect
The callback will
emits the “connected_event” on server-side
$(document).ready(function () {
var socket =
io.connect(); //Or given server url:
io.connect("http://xxxx:123")
socket.on('connect', function () { //The
default event: connect, when a connection is fired
console.log('Start connect!');
socket.emit('connected_event', { data: 'I\'m
connected!' });
});
});
▋Register event handlers on “server_response”
This handler will
receive the message: msg, from server-side and display it.
$(document).ready(function () {
var socket =
io.connect(); //Or given server url:
io.connect("http://xxxx:123")
// … skip
connect event handler
socket.on('server_response', function (msg) {
$('#log').append('<br>' + $('<div/>').text('Received #' + ': ' +
msg.data).html());
});
});
And HTML:
<pre id="log"></pre>
▋Broadcast message to all connected clients
Implement a Textbox
and button to send the message to other clients by emit “broadcast_event”.
$(document).ready(function () {
var socket =
io.connect(); //Or given server url:
io.connect("http://xxxx:123")
// … skip
connect event handler
// …
skip server_resposne event handler
$('#emitMsg').on('click', function () {
var msg = $('#msg').val();
socket.emit('broadcast_event', { data:
msg });
});
});
<input type="text" id="msg" />
<button id="emitMsg">Send Message
to all</button>
▋Demo
▋To stop the Flask-SocketIO
@app.route('/shutdown', methods=['POST'])
def shutdown():
socketio.stop()
▌Reference
沒有留言:
張貼留言