• Flask框架-1-[群聊]: flask-socketio实现websocket的功能


    一、项目结构

    flask_websocket

            |---static

                    |---js

                            |---jquery-3.7.0.min.js

                            |---socket.io_4.3.1.js

            |---templates

                    |---home

                            |---group_chat.html

                            |---index.html

            |---app.py

    1.1、python环境

    python3.9.0

    1.2、依赖包

    1. Flask==2.1.0
    2. eventlet==0.33.3
    3. Flask-SocketIO==5.3.4

    1.3、js文件下载

    https://code.jquery.com/jquery-3.7.0.min.js

    https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.3.1/socket.io.min.jsicon-default.png?t=N7T8https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.3.1/socket.io.min.js

    二、非群聊功能

    概述:项目中使用websocket,无法是为了实现实时更新数据。在某些数据上,需要能够实时更新数据或需要服务端主动向客户端推送更新的数据。

    2.1、前端index.html

    1. html>
    2. <html>
    3. <head>
    4. <script src="/static/js/socket.io_4.3.1.js">script>
    5. <script src="/static/js/jquery-3.7.0.min.js">script>
    6. <script type="text/javascript">
    7. var socket = io({
    8. query:{
    9. 'token':'123456'
    10. }
    11. });
    12. // 1、接收服务器端,给connect事件的响应,token验证成功服务器端才允许连接
    13. socket.on('success', function(message) {
    14. // 处理从服务器接收到的响应数
    15. alert(message)
    16. });
    17. //2、 接收来自服务器的'handle_data'事件,返回的数据
    18. socket.on('handle_data', function(message) {
    19. console.log(message)
    20. // 处理从服务器接收到的响应数
    21. const msg = message.msg;
    22. const $showDiv = $('#show');
    23. const pElement = $('

      ').text(msg);

    24. //添加到展示的div标签中
    25. $showDiv.append(pElement);
    26. });
    27. //3、 发送'handle_data'事件给服务器d
    28. function sendMessage() {
    29. var message = {"type":"user","id":1};
    30. //向后端获取id=1的用户的数据
    31. socket.emit('handle_data',message); //可以直接返回字典等数据
    32. }
    33. script>
    34. head>
    35. <body>
    36. <div id="show">
    37. div>
    38. <button onclick="sendMessage()">Send Messagebutton>
    39. body>
    40. html>

    2.2、后端相关接口,app.py

    1. from flask import Flask,render_template,request,jsonify
    2. from flask_socketio import SocketIO,send,emit,join_room
    3. app = Flask(__name__,static_folder='./static',template_folder='./templates')
    4. socketio = SocketIO(app,cors_allowed_origins='*')
    5. '''
    6. 一、非群聊功能,前端需要实时更新某些数据使用
    7. 1、返回html页面
    8. 2、主动发送websocket到后端,后端返回数据给请求的用户
    9. 3、调用某个视图函数,在视图函数中,给所有连接推送新的数据
    10. '''
    11. @app.route('/')
    12. def index():
    13. return render_template('home/index.html')
    14. @app.route('/user')
    15. def user():
    16. # 给房间名中的所有websocket,广播数据,告知所有连接去获取新的数据,
    17. socketio.emit('handle_data', {'data': '返回的数据', 'type': 'user', 'msg': '数据更新,广播到房间中返回的数据'}, room='default')
    18. return jsonify({'code': 200, 'data':'update data success!!!'})
    19. @socketio.on('handle_data')
    20. def handle_data(data):
    21. print(data,'接收浏览器发送的数据')
    22. #1、给发送给后端的websocket,发送数据,单独给这个websocket发送
    23. # socketio.emit('handle_data', {'data':'返回的数据','type':'user','msg':'单独返回'})
    24. emit('handle_data',{'data':'返回的数据','type':'user','msg':'主动请求时,返回的数据'})
    25. @socketio.on('connect')
    26. def handle_connect():
    27. print('connect连接')
    28. token = request.args.get('token')
    29. sid = request.sid
    30. print(request.args,'args')
    31. # print('连接的sid',request.sid)
    32. if token == '123456':
    33. socketio.emit('success','验证token成功')
    34. join_room('default') #加入到默认的房间中了
    35. #表明连接成功
    36. else:
    37. print('token验证失败')
    38. #阻止连接
    39. return False
    40. if __name__ == '__main__':
    41. socketio.run(app,debug=True)

    2.3、功能测试

    1、访问:http://127.0.0.1:5000 ,在发起连接时,传递了token,token验证成功才能建立连接

    2、点击 Send Message,模拟前端主动向后端发送信息,如获取指定数据,后端再返回指定数据

    3、新开一个标签访问:http://127.0.0.1:5000/user,模拟操作某些接口后,数据发生了变化,服务端主动将更新后的数据发给前端

    三、群聊功能

    概述:在web端实现群聊功能,实时收发消息。

    3.1、前端group_chat.html

    1. html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8">
    5. <title>群聊title>
    6. <script type="application/javascript" src="/static/js/jquery-3.7.0.min.js">script>
    7. <script type="application/javascript" src="/static/js/socket.io_4.3.1.js">script>
    8. <script type="application/javascript">
    9. //传递给模板的数据,转成python数据结构
    10. const data = {{ data|tojson }};
    11. const group = data.group; //群名
    12. const name = data.name;//当前用户名
    13. //1、发起连接
    14. const socket = io('http://'+document.domain+':'+location.port+'/chat',
    15. {query:{'token':'123456','group':group,'name':name}}
    16. );
    17. //2、监控群里中的消息
    18. socket.on('group_recv',function (data) {
    19. const msg = data.msg; //群里的消息
    20. const sendName = data.name; //发消息的人
    21. const sendType = data.type; //消息的类型
    22. const showDiv = $('#showDataId'); //展示消息的区域
    23. console.log(data)
    24. if (sendType==='connect'){
    25. //有人进入群里
    26. if (name===sendName){
    27. const pElement = $('

      ').text('欢迎您进入 '+group+' 群聊....');

    28. //添加到展示的div标签中
    29. showDiv.append(pElement);
    30. }else {
    31. const pElement = $('

      ').text('热烈欢迎'+sendName+'进入群聊....');

    32. //添加到展示的div标签中
    33. showDiv.append(pElement);
    34. }
    35. }else if (sendType==='data'){
    36. //有人群里发消息
    37. if (name===sendName){
    38. const pElement = $('

      ').text(msg);

    39. //添加到展示的div标签中
    40. showDiv.append(pElement);
    41. } else {
    42. const pElement = $('

      ').text(sendName+'> '+msg);

    43. //添加到展示的div标签中
    44. showDiv.append(pElement);
    45. }
    46. }else {
    47. //有人退出群里
    48. if (name === sendName) {
    49. } else {
    50. const pElement = $('

      ').text('公告: ' + sendName + '退出群里...');

    51. //添加到展示的div标签中
    52. showDiv.append(pElement);
    53. }
    54. }
    55. });
    56. //3、发送消息
    57. function sendDataFunc() {
    58. const $sendData = $('#sendDataId');
    59. socket.emit('group',{'group':group,'msg':$sendData.val(),'name':name});
    60. }
    61. script>
    62. head>
    63. <body>
    64. {#1、展示群聊的消息#}
    65. <div id="showDataId">
    66. div>
    67. {#2、发送消息的输入框#}
    68. <div>
    69. <input id="sendDataId" type="text">
    70. <input type="button" value="发送消息" onclick="sendDataFunc()">
    71. div>
    72. body>
    73. html>

    3.2、后端相关接口

    1. from flask import Flask,render_template,request,jsonify
    2. from flask_socketio import SocketIO,send,emit,join_room
    3. app = Flask(__name__,static_folder='./static',template_folder='./templates')
    4. socketio = SocketIO(app,cors_allowed_origins='*')
    5. '''
    6. 二、群聊相关的:使用名称空间=/chat
    7. 1、返回html页面的,地址栏中提取用户名和群名
    8. 2、后端接收js发送的消息,给群广播消息
    9. '''
    10. @app.route('/group/chat')
    11. def group_chat():
    12. group = request.args.get('group')
    13. name = request.args.get('name')
    14. return render_template('home/group_chat.html',data={'group':group,'name':name})
    15. @socketio.on('connect',namespace='/chat')
    16. def chat_connect():
    17. '''
    18. 控制群里用户进入群连接
    19. :return:
    20. '''
    21. token = request.args.get('token')
    22. name = request.args.get('name')
    23. group = request.args.get('group')
    24. print('群聊的连接:',request.args)
    25. if token:
    26. join_room(group)
    27. emit('group_recv',{'name':name,'msg':f'进入’{group}‘群聊','type':'connect'},room=group)
    28. else:
    29. return False
    30. @socketio.on('group',namespace='/chat')
    31. def handle_group(data):
    32. '''
    33. :param data: 用户在群聊中发送消息
    34. :return:
    35. '''
    36. print('chat群里发消息:',data)
    37. group = data.get('group')
    38. msg = data.get('msg')
    39. name = data.get('name')
    40. ret_data = {'msg':msg,'name':name,'type':'data'}
    41. emit('group_recv',ret_data,room=group)
    42. if __name__ == '__main__':
    43. socketio.run(app,debug=True)

    3.3、功能测试

    1、新开一个标签,访问:http://127.0.0.1:5000/group/chat?group=chat1&name=lhz

    2、新开一个标签,访问: http://127.0.0.1:5000/group/chat?group=chat1&name=yf

    3、新开一个标签,访问:http://127.0.0.1:5000/group/chat?group=chat1&name=zzh

    4、在任意一个输入框中输入信息并发送

  • 相关阅读:
    Python - Numpy库的使用(简单易懂)
    读书笔记: 如何把一件事做到最好
    【Apache Flink 介绍与学习】
    邻接矩阵无向图(二) - C++实现
    关于LWIP的一点记录(四)
    NIO BIO AIO个人复习笔记整理
    JVM内存模型
    蓝桥杯备战刷题-滑动窗口
    QuEra将研发可重构中性原子量子计算机
    python+django固定资产管理系统项目源码
  • 原文地址:https://blog.csdn.net/weixin_46371752/article/details/133064384