websocket的简单了解和python应用
序
web时代,http协议是当之无愧的幸运儿,它是在TCP传输层协议的基础上,建立的web应用层协议,主要进行html文本的传输,其他的都能算是http当中元素的渲染。早期只是简单的html文本,后续引入css优化了样式,美化了显示,然后的js又加强了动态渲染,而后后续的种种web框架在提升程序员开发效率的同时,也进行各种安全和性能上的优化。但有一点不变的是,http服务端只能被动地去接收来自客户端的请求,在经历后台处理以后,再做出响应。
针对这种被动的单向请求,当服务器存在信息变更的时候,想要主动推送信息给客户就非常麻烦。为此而生的技术,有js种的自动请求,在构建网页的时候,就事先做好了js设定,在一定情况下或者时间内,组织客户端技术发起请求;但这种技术能用,但不够美观,效率也没有跟上预期,在设计上更理想的就是,服务器在信息进行变更的情况下,马上推送更新后信息给客户端,而websocket就应了这种需求而诞生。
实现
websocket是单个TCP连接上全双工通信,在客户端和服务端进行一次握手后,就可以实现持续连接,从而进行数据的双向传输。在客户端或者服务端任意一方发起建立websocket通信的请求以后,对端进行确认式回应,然后一个类似tcp的连接建立,因此常用于IM通信的情景。
websocket和http相同的地方,都是基于TCP的可靠性传输的应用层协议;不同的是websocket是双向的,http是单向的,而且websocket通信前,需要发起一个握手连接,而客户端在http请求发起前,服务端并不知道对端存在。
实现原理:在websocket通信前,通信是http形式,而两者都是基于TCP连接的,所以websocket连接的握手,客户端就是在TCP连接建立以后,在http头中放进去特定的信息,如下:
GET /chat HTTP/1.1 Host: www.example.com Upgrade: websocket Connection: Upgrade
上面表示客户端准备升级连接为长连接的websocket,而服务器的成功回应是这样的:
HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade
响应成功以后,tcp连接就这么长久维持,双方传输的信息大多是json格式的文本信息。因为是基于TCP的通信,所以它的各种特点都是和tcp相仿的。
websocket在flask中的应用
flask是一个轻量级的web框架,它本身可以提供简单的web api,但如果想要更多的功能,就需要自己去寻找插件的支持了,也是因为这些丰富的插件,才使得flask应用广泛。websocket在flask中的应用,就是flask-sockets和flask_socketIO,前者是对websocket的简单实现,对于已经实现了websocket支持的浏览器友好,丑拒旧版不支持websocket的浏览器;后者的功能是前者的丰富和补全,因为它支持旧版,能做到这点,就已经很足够了。
flask_sockets使用
进行试验以前,当然要进行经典的pip:
pip install flask pip install flask-cors pip install flask-sockets
示例如下:
from flask import Flask, render_template from flask_sockets import Sockets from flask_cors import * from time import sleep app = Flask(__name__) socket = Sockets(app) CORS(app, supports_credentials=True) # 返回一个内含websocket请求发起js的html @app.route('/') def home(): return render_template('index.html') @socket.route('/hello') def hello(ws): print('websocket处理') while not ws.closed(): ws.send("你大爷") sleep(3) if __name__ == '__main__': from gevent import pywsgi from geventwebsocket.handler import WebSocketHandler server = pywsgi.WSGIServer(('',8090), app, handler_class=WebSocketHandler) print('服务开启监听') server.serve_forever()
主要是给一个主页面,使其返回一个内含链接的html页面,它内含js,在点击跳转的时候可以进行websocket的请求构造:
<!DOCTYPE html> <html> <body> <div align="center"> <h1>Welcome,My Friend.</h1> <a href="javascript:enter()">来进入下一个领域吧</a> </div> </body> <script> function enter(){ if ('WebSocket' in window){ // 创建websocket即发起请求 var web_socket = new WebSocket("ws://localhost:8090/hello") // 设置onmessage事件的回调,也就是接收数据 web_socket.onmessage = function(event){ console.log(event.data) } // 设置onopen的回调 web_socket.onopen = function(){ console.log("开始连接") } // 设置onclose的回调 web_socket.onclose = function(event) { console.log('连接结束:'+event.code) } } else { alert('浏览器不支持websocket') } } </script> </html>
当然,设置一个带有点击事件的button也不是不可以。
... <button onclick="enter(this)">来进入下一个领域吧</button> ...
去前台f12一下,可以看到hello请求的请求头:
和响应:
flask-socketIO使用
使用前同样需要安装一下:
pip install flask pip install flask-socketIO
实例:
from flask import Flask, render_template from flask_socketio import SocketIO, emit app = Flask(__name__) app.config['SECRET_KEY'] = 'test' socketIo = SocketIO() # 添加cors支持,解决跨域问题 socketIo.init_app(app, cors_allowed_origin='*') name_space = '/hello' @app.route('/') def home(): return render_template('index.html') @app.route('/push') def push_msg(): event_name = 'hello' broadcasted_data = {'data':'test'} # 广播信息 socketIo.emit(event_name, broadcasted_data, broadcast=False, namespace=name_space) return 'over' # 设置websocket连接建立后回调 @socketIo.on('connect', namespace=name_space) def connect(): print(f'websocket连接已建立,namespace:{name_space}') # 设置websocket连接断开后回调 @socketIo.on('disconnect', namespace=name_space) def disconnect(): print(f'websocket连接已断开,namespace:{name_space}') @socketIo.on('event1', namespace=name_space) def test(msg): print(f'客户端:{msg}') emit('response', {'data':msg['data'], 'count':1}) if __name__ == '__main__': # 不像往常的app.run,这里不显示运行所在 socketIo.run(app,host='0.0.0.0', port=8090)
在js中,使用jquery也可以构建websocekt通信,下面有一个加载ajax的例子,就是在加载了html以后,它的js自动请求后续内容,进行渲染:
<script> $(document).ready(function () { namespace = '/hello'; var socket = io.connect(location.protocol + '//' + document.domain + ':' + location.port + namespace); socket.on('hello', function (res) { var data_show = res.data; if (data_show) { $("#data_show").append(data_show).append('<br/>'); } }); }); </script>
但在实践的时候,却问题百出,一个是没有引入js库
<header> <script src="https://lib.baomitu.com/jquery/1.12.4/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.3/socket.io.js"></script> </header>
一个是python的flask-socketIO、python-socketIO和python-engineIO版本不搭,使用下面图片对标的版本进行安装,后面又有其他问题ImportError: cannot import name 'run_with_reloader' from 'werkzeug.serving'
,所以先放着吧。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· Vue3状态管理终极指南:Pinia保姆级教程