Python 基于 Flask 框架实现 Websocket 实时通信详细教程(待更新)

websocket http 区别

WebSocket 是 HTML5 出的东西(协议),也就是说HTTP协议没有变化,或者说没关系,但HTTP是不支持持久连接的(长连接,循环连接的不算)

首先HTTP有 1.1 和 1.0 之说,也就是所谓的 keep-alive ,把多个HTTP请求合并为一个,但是 Websocket 其实是一个新协议,跟HTTP协议基本没有关系,只是为了兼容现有浏览器的握手规范而已,也就是说它是HTTP协议上的一种补充可以通过这样一张图理解:
在这里插入图片描述

注意:有交集但是并不是全部。

GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com

socket 流程

在这里插入图片描述

服务器端 flask_sockets

flask实现 websocket 的两种方式

第一种是 flask_sockets 方式,该方式是flask对websocket的最原始封装,功能较为单一。

第二种方式 Flask-SocketIO 对 websocket 的封装,该方式所能提供功能较多,不但实现了socket的基本通信功能,也可以结合flask相关接口,使其更加完备,因此网上对该api介绍也较多。

flask_sockets 实现介绍

@sockets.route('/echo')
def echo_socket(ws):
    print("connection start")
    while not ws.closed:
        msg = ws.receive() # 同步阻塞
        print(msg)
        now = datetime.datetime.now().isoformat()
        ws.send(now)  # 发送数据
        time.sleep(1)

客户端发送数据实现

<button onclick="send()">发送</button>


var ws = new WebSocket("ws://127.0.0.1:8080/echo")
ws.onmessage = function (event) {
    console.log(event.data)
};

function send(){
    ws.send("hello world")
}

服务器端完整代码展示

from flask import Flask
from flask_sockets import Sockets
import datetime

app = Flask(__name__)
sockets = Sockets(app)

from flask_cors import *
CORS(app, supports_credentials=True)

@sockets.route('/echo')
def echo_socket(ws):
    print("hello")
    while not ws.closed:
        msg = ws.receive()
        print(msg)
        now = datetime.datetime.now().isoformat()
        ws.send(now)  #发送数据

@app.route('/')
def hello_world():
    return 'Hello World!'

if __name__ == "__main__":
    from gevent import pywsgi
    from geventwebsocket.handler import WebSocketHandler
    server = pywsgi.WSGIServer(('0.0.0.0', 8080), app, handler_class=WebSocketHandler)
    print('server start')
    server.serve_forever()
var ws = new WebSocket("ws://127.0.0.1:8080/echo")
ws.onmessage = function (event) {
    console.log(event.data)
}
ws.onopen = function() {
    console.log("start connection")
}
ws.onclose = function(e){
    console.log("connection closed (" + e.code + ")");
}

服务器端 Flask-SocketIO

debug的好处:已经run过的程序,Ctrl+S,保存一下,自动重启,(节省时间,提高效率)

可以分为开发模式,和生产模式;在程序员自己写代码的时候,即 app.run(debug=True),写完程序,递交项目最终成果时,要将其关闭,即 app.run()

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 = '/echo'

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

@app.route('/push')
def push_once():
    event_name = 'echo'
    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__':
    socketio.run(app, host='0.0.0.0', port=5000)

客户端的实现:

<div id="data_show"></div>

<script>
$(document).ready(function () {
    namespace = '/echo';
    var socket = io.connect(location.protocol + '//' + document.domain + ':' + location.port + namespace);
    socket.on('echo', function (res) {
        var data_show = res.data;
        if (data_show) {
            $("#data_show").append(data_show).append('<br/>');
        }
    });
});
</script>

socketio 中的 namespace 的概念

如果希望服务端发送的信息在所有客户端都能收到,那么使用默认的namespace / 就好了。但是如果想把发送信息的服务器作为第三方应用给不同客户端使用,就需要为每一个客户端定义一个namespace.

跨域问题的解决方案:
在这里插入图片描述
采用 flask_cors 进行解决跨域问题

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

版本不兼容问题:

pip list 查看 服务器端 Flask-SocketIO 版本
在这里插入图片描述
查看 vue 客户端的 socketIO 版本
在这里插入图片描述

Vue 使用 socket.io

通过最近一系列的踩坑之后,总结出了这篇相对较为完善的关于vue-socket.io的使用文章,包含大家困扰的(socket连接、断开重连,以及当连接的地址是动态的情况下,我们应该注意的事项。

如何安装 socket.io

npm install vue-socket.io --save

第一种:引用 socket.io,在组件中直接引入

import io from 'socket.io-client'

第二种:引用 socket.io,在 main.js 中直接这样写

import VueSocketIO from 'vue-socket.io'

Vue.use(new VueSocketIO({
    debug: true,
    connection: 'ws://localhost:5000/echo',  //
}))

这里要提示的一点就是,当连接的地址是动态的,代码的执行顺序就很重要了,即 new VueSocket 在main.js中的位置

如何进行建立 socket.io 连接

在 html 中直接实现:

 <html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://cdn.bootcdn.net/ajax/libs/socket.io/4.4.1/socket.io.min.js"></script>
    <title>socket.io</title>
</head>
    <button onclick="send()">发送信息</button>
<body>
    <script>
        var socket = null
        function initWebSocket() {
            socket = io.connect('ws://localhost:5000/echo', {
                timeout: 300000,
                reconnectionDelayMax: 1000,
                reconnectionDelay: 500
            })
            socket.on('connect', () => {
                console.log('建立链接')
                socket.emit('message', { 'data': 'I\'m connected!' })
            })
            socket.on('disconnect', () => {
                console.log('连接断开')
                socket.emit('message', { 'data': 'I\'m disconnected!' });
            })
            socket.on('card message', msg => {
                // 接受数据
            })
            socket.on('error message', msg => {
                console.log('error:' + msg)
                
            })
        }
        function send(){
            socket.emit('message', { 'data': 'I\'m disconnected!' })
        }

        initWebSocket()
    </script>
</body>

</html>

在 Vue 组件 中直接实现:

initWebSocket () {
	this.socket = null
	this.socket = io.connect('ws://localhost:5000/namespace', {
		timeout: 300000,
		reconnectionDelayMax: 1000,
		reconnectionDelay: 500
	})
	this.socket.on('connect', () => {
		console.log('建立链接')
		this.socket.emit(传参)
	})
	this.socket.on('disconnect', () => {
		console.log('连接断开')
	})
	this.socket.on('card message', msg => {
	 	// 接受数据
	})
	this.socket.on('error message', msg => {
		console.log('error:' + msg)
	})
}

网页客户端实现

首先看下四个方法

onclose: ((this: WebSocket, ev: CloseEvent) => any) | null;

onerror: ((this: WebSocket, ev: Event) => any) | null;

onmessage: ((this: WebSocket, ev: MessageEvent) => any) | null;

onopen: ((this: WebSocket, ev: Event) => any) | null;

建立 ws 对象,绑定 onmessage 方法进行接受服务器端传来的数据

var ws = new WebSocket("ws://127.0.0.1:8080/echo")

ws.onmessage = function (event) {
    console.log(event.data)
};

ws.onopen = function() {
   console.log("start connection")
};

ws.onclose = function(e){
   console.log("connection closed (" + e.code + ")");
};

BootCDN 稳定、快速、免费的前端开源项目 CDN 加速服务

https://cdn.bootcdn.net/ajax/libs/socket.io/4.4.1/socket.io.esm.min.js

<script src="https://cdn.bootcdn.net/ajax/libs/socket.io/4.4.1/socket.io.esm.min.js"></script>

常见问题报错解决方案

ImportError 无法导入 ContextVar 包

ImportError: cannot import name ‘ContextVar’

pip uninstall flask   
# 卸载  你也可以省略这步,直接pip install flask==1.0
pip install flask==1.0   
# 我这里改成1.0就行了,改成其他低版本应该也没问题,有兴趣自己试下

关于 Werkzeug 缺失,或者版本过低问题

werkzeug.routing.WebsocketMismatch: 400 Bad Request: The browser (or proxy) sent a request that this server could not understand.

2022-04-27T12:31:24Z { REMOTE_ADDR : 127.0.0.1 , REMOTE_PORT : 63825 , HTTP_HOST : 127.0.0.1:8080 , (hidden keys: 30)} failed with WebsocketMismatch

pip install Werkzeug==1.0.1 -i https://mirrors.aliyun.com/pypi/simple/

flask 缺少 Werkzeug,或者 Werkzeug 版本不兼容 flask 等问题

flask 2.0.2 requires Werkzeug>=2.0, but you have werkzeug 1.0.1 which is incompatible.

关于客户端的 socket 和 flask 端的 socket 版本不兼容

The client is using an unsupported version of the Socket.IO or Engine.IO protocols (further occurrences of this error will be logged with level INFO)

  • 12
    点赞
  • 98
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
基于Python+Flask websocket 和 vue 的实时聊天项目-毕业设计源码+使用文档(高分优秀项目) 该项目是个人高分毕业设计项目源码,已获导师指导认可通过,答辩评审分达到97分,在window10/11测试环境严格调试,下载即用,确保可以运行,部署教程齐全,也可以作为课程设计 基于Python+Flask websocket 和 vue 的实时聊天项目-毕业设计源码+使用文档(高分优秀项目) 该项目是个人高分毕业设计项目源码,已获导师指导认可通过,答辩评审分达到97分,在window10/11测试环境严格调试,下载即用,确保可以运行,部署教程齐全,也可以作为课程设计 基于Python+Flask websocket 和 vue 的实时聊天项目-毕业设计源码+使用文档(高分优秀项目) 该项目是个人高分毕业设计项目源码,已获导师指导认可通过,答辩评审分达到97分,在window10/11测试环境严格调试,下载即用,确保可以运行,部署教程齐全,也可以作为课程设计 基于Python+Flask websocket 和 vue 的实时聊天项目-毕业设计源码+使用文档(高分优秀项目) 该项目是个人高分毕业设计项目源码,已获导师指导认可通过,答辩评审分达到97分,在window10/11测试环境严格调试,下载即用,确保可以运行,部署教程齐全,也可以作为课程设计 基于Python+Flask websocket 和 vue 的实时聊天项目-毕业设计源码+使用文档(高分优秀项目) 该项目是个人高分毕业设计项目源码,已获导师指导认可通过,答辩评审分达到97分,在window10/11测试环境严格调试,下载即用,确保可以运行,部署教程齐全,也可以作为课程设计
### 回答1: Python Flask WebSocket是一种基于Python Flask框架实时通信协议,它可以在Web应用程序中实现双向通信WebSocket协议允许服务器和客户端之间建立一个持久的连接,从而可以实时地传输数据。使用Python Flask WebSocket可以实现实时聊天、实时数据更新等功能。 ### 回答2: Python Flask WebSocket 是基于 Python 编程语言和 Flask 框架的一种实时通信协议。这种协议可以使 Web 应用程序实现实时通信功能,而不需要通过发送 HTTP 请求和接收响应来完成。 WebSocket 协议最初是由浏览器开发者和Web 开发者所设计的一种新型应用程序协议。与普通的HTTP协议不同,WebSocket可以允许在服务端和客户端之间进行双向通信。在 WebSocket 协议中,服务端和客户端可以随时发送消息,而且消息的发送和接收是非常快速的。这一功能可以帮助开发者设计出具有实时性的 Web 应用程序,在现代的 Web 应用中,实时性的需求越来越大。 Flask 是一个轻量级的 Web 框架,可以帮助我们快速构建 Web 应用程序。它使用 Python 编程语言,允许我们以一种简单的方式处理 URL、读取 POST 和 GET 请求、执行会话管理等等。 在 Python Flask WebSocket 中,我们可以使用 Flask-SocketIO 扩展来实现 WebSocket 功能。Flask-SocketIO 扩展可以使我们更加容易地实现 WebSocket实时通信功能。Flask-SocketIO 充分利用了服务器和客户端之间的 WebSocket 连接,实现了在服务器端和客户端之间的双向通信。 在 Python Flask WebSocket 中,我们可以使用多个库和工具来实现 WebSocket 功能。常用的库包括 Flask-SocketIO、Gevent-WebSocket、Werkzeug-WebSocket、等等。使用这些工具,开发者可以在服务器端和客户端之间轻松地实现实时通信功能,通过 WebSocket 协议实现双向通信。这对于开发实时性需求较强的 Web 应用程序尤为重要。 ### 回答3: Python Flask是一款用于Web应用程序开发的微型框架,其设计简单易用且易于扩展,因此广泛应用于Web开发领域。WebSocket是一种基于TCP协议的全双工通信协议,使得客户端和服务器可以实时交换数据。Python Flask框架已经内置了与WebSocket交互所需的库,因此可以轻松地使用Python Flask来创建WebSocket应用程序。 在Python Flask中,可以使用Flask-SocketIO库来方便地使用WebSocket服务。通过使用Flask-SocketIO库,可以轻松地实现WebSocket的全双工通信实时地向客户端发送数据,还可以处理客户端发送过来的数据。此外,Flask-SocketIO还支持使用Room来组织客户端,可以让客户端按照分组的方式,实现更加灵活的数据传输方式。 使用Python Flask开发WebSocket应用程序,需要以下步骤: 1. 安装Flask-SocketIO库。可以使用pip命令来安装它。 2. 导入Flask-SocketIO库。 3. 在Flask应用程序中创建SocketIO对象,以接受WebSocket连接。 4. 定义相关的事件处理函数。例如,当客户端与服务器建立连接时的事件处理函数。 5. 使用SocketIO对象,将事件处理函数与相应事件绑定。例如,将“connect”事件绑定到连接事件处理函数上。 6. 使用SocketIO对象,启动WebSocket服务。例如,使用run()方法启动Web应用程序。 Python FlaskWebSocket功能使得开发实时应用程序变得更加容易和灵活。使用WebSocket可以在不重新加载页面的情况下实现客户端和服务器之间的实时通信。如果你想开发一些需要实时通信功能的应用程序,那么Python Flask提供的WebSocket服务是一个非常不错的选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

唤醒手腕

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值