This is the 23rd day of my participation in the August More Text Challenge.More challenges in August
Hardware and software Environment
- windows 10 64bit
- Anaconda3 with python 3.7
- Pycharm 2020.1.2
- Flask 1.1.2
- Flask – socketio 4.3.1
What is the websocket
WebSocket is a network communication protocol. Different from HTTP, WebSocket provides full-duplex communication. That is to say, in the traditional way, only when the client initiates a request, the server will send data, but WebSocket can let the server actively send data to the client, it is a server push technology.
The following figure shows the difference between WebSocket and HTTP
websocketd
Websocketd is a very good WebSocket server, we first use it to understand the standard WebSocket interaction. Download the Windows version of WebSocketd, unpack it, and go to the directory
Now write a test script in Python named test.py that periodically prints a value to the standard output stdout
From sys import stdout from time import sleep for count in range(0, 10): print(count + 1) stdout.flush() sleep(0.5)Copy the code
Open the service
websocketd --port 8080 python test.py
Copy the code
Now need a WebSocket client, we came to the chrome store, installing a plug-in chrome.google.com/webstore/de… “, and then open the plugin, enter the URL of the WebSocket to see the output on the server side
flask-socketio
Flask-socketio enables Flask applications to access low-latency two-way communication between clients and servers. Client applications can use Javascript, C++, Java, and any SocketIO official client library in Swift or any compatible client to establish a permanent connection to the server.
Asynchronous mode
Flask-socketio requires the support of low-level asynchronous services. It is flexible enough to detect asynchronous services in the current environment in the order of eventlet > gEvent > Werkzeug
eventlet
Best performance, support long polling andWebSocket
transmissiongevent
Supported in many different configurations.gevent
Full support for long polling transfer, but witheventlet
Different,gevent
Not the nativeWebSocket
Support. To add toWebSocket
The support currently has two options: installgevent-websocket
Package forgevent
increaseWebSocket
Support, or you can use withWebSocket
The function ofuWSGI Web
The server.gevent
The use of is also a high performance option, but slightly lesseventlet
werkzeug
Can also be used based onwerkzeug
theFlask
Development server, however, it is important to note that it lacks the performance of the other two options, so it is only suitable for simple development environments, and it only supports long polling transport
The installation
Use PIP directly to install
pip install eventlet
pip install flask-socketio
Copy the code
The sample code
Look at the server-side code first
File run. Py
from flask import Flask, render_template from flask_socketio import SocketIO, emit app = Flask(__name__) app.config['SECRET_KEY'] = 'secret_key' socketio = SocketIO() socketio.init_app(app, cors_allowed_origins='*') name_space = '/dcenter' @app.route('/') def index(): return render_template('index.html') @app.route('/push') def push_once(): event_name = 'dcenter' broadcasted_data = {'data': "test message!" } socketio.emit(event_name, broadcasted_data, broadcast=False, namespace=name_space) return 'done! ' @socketio.on('connect', namespace=name_space) def connected_msg(): print('client connected.') @socketio.on('disconnect', namespace=name_space) def disconnect_msg(): print('client disconnected.') @socketio.on('my_event', namespace=name_space) def mtest_message(message): print(message) emit('my_response', {'data': message['data'], 'count': 1}) if __name__ == '__main__': = '0.0.0.0 socketio. Run (app, the host', the port = 5000, debug = True)Copy the code
In the code, we set up the namespace, because the url that the client needs to connect contains namespace, and there is also the concept of event, connect, disconnect and custom my_event
The code for the index.html file is as follows
<! DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>SocketIO Demo</title> <script type="text/javascript" SRC = "/ / cdn.bootcss.com/jquery/3.1.1/jquery.min.js" > < / script > < script type = "text/javascript" SRC = "/ / cdn.bootcss.com/socket.io/1.5.1/socket.io.min.js" > < / script > < / head > < body > < h2 > Demo of SocketIO < / h2 > < div id="t"></div> <script> $(document).ready(function () { namespace = '/dcenter'; var socket = io.connect(location.protocol + '//' + document.domain + ':' + location.port + namespace); socket.on('dcenter', function (res) { var t = res.data; if (t) { $("#t").append(t).append('<br/>'); }}); }); </script> </body> </html>Copy the code
After starting the service, we go to http://127.0.0.1:5000 and leave the page untouched because it will display the messages we receive later
At that time, use the browser to http://127.0.0.1:5000/push
We use this method to trigger the server to send a message to the client, and go back to the previous page to see that the message sent from the server is displayed on the page
Note that in the javascript above, the PROTOCOL used in the URL is HTTP, not WS, which is a bit different from the native WebSocket.
Cors cross-domain error
If the front and back ends are separated, the following error occurs
Traceback (most recent call last): File "src\gevent\greenlet.py", line 854, in gevent._gevent_cgreenlet.Greenlet.run File "C:\ProgramData\Anaconda3\envs\FlaskTutorial\lib\site-packages\gevent\baseserver.py", line 34, in _handle_and_close_when_done return handle(*args_tuple) File "C:\ProgramData\Anaconda3\envs\FlaskTutorial\lib\site-packages\gevent\server.py", line 233, in wrap_socket_and_handle with _closing_socket(self.wrap_socket(client_socket, **self.ssl_args)) as ssl_socket: TypeError: wrap_socket() got an unexpected keyword argument 'cors_allowed_origins' 2020-09-09T08:16:07Z <Greenlet at 0x1812f1e8bf8: _handle_and_close_when_done(<bound method StreamServer.wrap_socket_and_handle , <bound method StreamServer.do_close of <WSGIServer, (<gevent._socket3.socket [closed] at 0x1812fc41cc8)> failed with TypeErrorCopy the code
This is a cross-domain problem. After testing, we found that using flask-CORS, which was introduced earlier, does not work. We need to add the necessary parameters during socketio initialization
socketio = SocketIO()
socketio.init_app(app, cors_allowed_origins='*')
Copy the code
Detailed information can be found at github.com/eventlet/ev…
Download the source code
Github.com/xugaoxiang/…
Flask Series of Tutorials
For more Flask tutorials, go ahead
Xugaoxiang.com/category/py…
The resources
- websocketd.com/
- Github.com/miguelgrinb…
- flask-socketio.readthedocs.io/en/latest/
- Stackoverflow.com/questions/6…
- Zh.wikipedia.org/wiki/Socket…
- Juejin. Im/post / 684490…
- Github.com/miguelgrinb…
- Github.com/miguelgrinb…