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、依赖包

python 复制代码
Flask==2.1.0
eventlet==0.33.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.jshttps://cdnjs.cloudflare.com/ajax/libs/socket.io/4.3.1/socket.io.min.js

二、非群聊功能

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

2.1、前端index.html

html 复制代码
<!DOCTYPE html>
<html>
<head>
    <script src="/static/js/socket.io_4.3.1.js"></script>
    <script src="/static/js/jquery-3.7.0.min.js"></script>
    <script type="text/javascript">

        var socket = io({
        query:{
            'token':'123456'
        }
        });
         // 1、接收服务器端,给connect事件的响应,token验证成功服务器端才允许连接
        socket.on('success', function(message) {
            // 处理从服务器接收到的响应数
            alert(message)
        });

        //2、 接收来自服务器的'handle_data'事件,返回的数据
        socket.on('handle_data', function(message) {
             console.log(message)
            // 处理从服务器接收到的响应数
            const msg = message.msg;
            const $showDiv = $('#show');
            const pElement = $('<p>').text(msg);
            //添加到展示的div标签中
            $showDiv.append(pElement);
        });



        //3、 发送'handle_data'事件给服务器d
        function sendMessage() {
            var message = {"type":"user","id":1};
            //向后端获取id=1的用户的数据
            socket.emit('handle_data',message); //可以直接返回字典等数据

        }
    </script>
</head>
<body>
    <div id="show">

    </div>
    <button onclick="sendMessage()">Send Message</button>

</body>
</html>

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

python 复制代码
from flask import Flask,render_template,request,jsonify
from flask_socketio import SocketIO,send,emit,join_room

app = Flask(__name__,static_folder='./static',template_folder='./templates')
socketio = SocketIO(app,cors_allowed_origins='*')

'''
一、非群聊功能,前端需要实时更新某些数据使用
1、返回html页面
2、主动发送websocket到后端,后端返回数据给请求的用户
3、调用某个视图函数,在视图函数中,给所有连接推送新的数据
'''

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

@app.route('/user')
def user():
    # 给房间名中的所有websocket,广播数据,告知所有连接去获取新的数据,
    socketio.emit('handle_data', {'data': '返回的数据', 'type': 'user', 'msg': '数据更新,广播到房间中返回的数据'}, room='default')
    return jsonify({'code': 200, 'data':'update data success!!!'})

@socketio.on('handle_data')
def handle_data(data):
    print(data,'接收浏览器发送的数据')
    #1、给发送给后端的websocket,发送数据,单独给这个websocket发送
    # socketio.emit('handle_data', {'data':'返回的数据','type':'user','msg':'单独返回'})
    emit('handle_data',{'data':'返回的数据','type':'user','msg':'主动请求时,返回的数据'})


@socketio.on('connect')
def handle_connect():
    print('connect连接')
    token = request.args.get('token')
    sid = request.sid
    print(request.args,'args')
    # print('连接的sid',request.sid)

    if token == '123456':
        socketio.emit('success','验证token成功')
        join_room('default') #加入到默认的房间中了
        #表明连接成功
    else:
        print('token验证失败')
        #阻止连接
        return False

if __name__ == '__main__':
    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

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>群聊</title>
    <script type="application/javascript" src="/static/js/jquery-3.7.0.min.js"></script>
    <script type="application/javascript" src="/static/js/socket.io_4.3.1.js"></script>
    <script type="application/javascript">
        //传递给模板的数据,转成python数据结构
        const data = {{ data|tojson }};
        const group = data.group; //群名
        const name = data.name;//当前用户名
        //1、发起连接
        const socket = io('http://'+document.domain+':'+location.port+'/chat',
            {query:{'token':'123456','group':group,'name':name}}
        );


        //2、监控群里中的消息
        socket.on('group_recv',function (data) {
            const msg = data.msg; //群里的消息
            const sendName = data.name; //发消息的人
            const sendType = data.type; //消息的类型
            const showDiv = $('#showDataId'); //展示消息的区域
            console.log(data)
            if (sendType==='connect'){
                //有人进入群里
                if (name===sendName){
                    const pElement = $('<p>').text('欢迎您进入 '+group+' 群聊....');
                    //添加到展示的div标签中
                    showDiv.append(pElement);
                }else {
                    const pElement = $('<p>').text('热烈欢迎'+sendName+'进入群聊....');
                    //添加到展示的div标签中
                    showDiv.append(pElement);
                }

            }else if (sendType==='data'){
                //有人群里发消息
                if (name===sendName){
                    const pElement = $('<p>').text(msg);
                    //添加到展示的div标签中
                    showDiv.append(pElement);
                } else {
                    const pElement = $('<p>').text(sendName+'> '+msg);
                    //添加到展示的div标签中
                    showDiv.append(pElement);
                }
            }else {
                //有人退出群里
                if (name === sendName) {

                } else {
                    const pElement = $('<p>').text('公告: ' + sendName + '退出群里...');
                    //添加到展示的div标签中
                    showDiv.append(pElement);
                }
            }

        });

        //3、发送消息
        function sendDataFunc() {
           const $sendData = $('#sendDataId');
           socket.emit('group',{'group':group,'msg':$sendData.val(),'name':name});
        }

    </script>
</head>
<body>

{#1、展示群聊的消息#}
<div id="showDataId">

</div>

{#2、发送消息的输入框#}
<div>
    <input id="sendDataId" type="text">
    <input type="button" value="发送消息" onclick="sendDataFunc()">
</div>

</body>
</html>

3.2、后端相关接口

python 复制代码
from flask import Flask,render_template,request,jsonify
from flask_socketio import SocketIO,send,emit,join_room

app = Flask(__name__,static_folder='./static',template_folder='./templates')
socketio = SocketIO(app,cors_allowed_origins='*')

''' 
二、群聊相关的:使用名称空间=/chat 
1、返回html页面的,地址栏中提取用户名和群名
2、后端接收js发送的消息,给群广播消息
'''
@app.route('/group/chat')
def group_chat():
    group = request.args.get('group')
    name = request.args.get('name')
    return render_template('home/group_chat.html',data={'group':group,'name':name})

@socketio.on('connect',namespace='/chat')
def chat_connect():
    '''
    控制群里用户进入群连接
    :return:
    '''
    token = request.args.get('token')
    name = request.args.get('name')
    group = request.args.get('group')
    print('群聊的连接:',request.args)
    if token:
        join_room(group)
        emit('group_recv',{'name':name,'msg':f'进入'{group}'群聊','type':'connect'},room=group)
    else:
        return False

@socketio.on('group',namespace='/chat')
def handle_group(data):
    '''
    :param data: 用户在群聊中发送消息
    :return:
    '''
    print('chat群里发消息:',data)
    group = data.get('group')
    msg = data.get('msg')
    name = data.get('name')
    ret_data = {'msg':msg,'name':name,'type':'data'}
    emit('group_recv',ret_data,room=group)



if __name__ == '__main__':
    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、在任意一个输入框中输入信息并发送

相关推荐
databook14 小时前
Manim实现闪光轨迹特效
后端·python·动效
Juchecar15 小时前
解惑:NumPy 中 ndarray.ndim 到底是什么?
python
用户83562907805115 小时前
Python 删除 Excel 工作表中的空白行列
后端·python
Json_15 小时前
使用python-fastApi框架开发一个学校宿舍管理系统-前后端分离项目
后端·python·fastapi
数据智能老司机1 天前
精通 Python 设计模式——分布式系统模式
python·设计模式·架构
数据智能老司机1 天前
精通 Python 设计模式——并发与异步模式
python·设计模式·编程语言
数据智能老司机1 天前
精通 Python 设计模式——测试模式
python·设计模式·架构
数据智能老司机1 天前
精通 Python 设计模式——性能模式
python·设计模式·架构
c8i1 天前
drf初步梳理
python·django
每日AI新事件1 天前
python的异步函数
python