Flask框架-2-[单聊]: flask-socketio实现websocket的功能,实现单对单聊天,flask实现单聊功能

news2025/1/4 5:32:36

一、概述和项目结构

在使用flask-socketio实现单聊时,需要将会话id(sid) 与用户进行绑定,通过emit('事件','消息',to=sid) ,就可以把消息单独发送给某个用户了。

flask_websocket

        |--static

                |--js

                        |--jquery-3.7.0.min.js

                        |--socket.io_4.3.1.js

        |--templates

                |--chat

                        |--single.html

        |--app.py

1.1、python版本

python3.9.0

1.2、依赖包

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.jsicon-default.png?t=N7T8https://code.jquery.com/jquery-3.7.0.min.jshttps://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

       

二、具体代码

2.1、具体逻辑

1、先请求http://127.0.0.1:5000/single/chat?name=lhz     与后端建立连接,将会用户名与会话id绑定关系

2、指定消息发送给哪个用户

3、展示在线的用户名字,用户退出连接时通知其他用户

2.2、app.py       

from flask import Flask,render_template,request,jsonify
from flask_socketio import SocketIO,send,emit,join_room,leave_room

app = Flask(__name__,static_folder='./static',template_folder='./templates')
socketio = SocketIO(app,cors_allowed_origins='*',async_mode ='eventlet')
from flask_socketio import ConnectionRefusedError

'''
单对单聊天功能
1、用户连接时,携带上用户名,sid记录到该用户名的字典中
2、通过sid实现单聊
3、通过sid判断用户是否在线中
'''

USER = {}  #{'lhz':{'sid':'xxxx'}}

@app.route('/single/chat')
def single():
    name = request.args.get('name')
    return render_template('chat/single.html',data={'name':name})

class SingleChat(Namespace):
    def on_connect(self):
        name = request.args.get('name')
        sid = request.sid
        # 把当前用户写入到在线中
        if name in USER:
            print('有其他用户了', '直接覆盖')
            # raise ConnectionRefusedError('用户已经在线了')
            USER[name] = {'sid': sid}
        else:
            USER[name] = {'sid': sid}
            # send({'code':200,'msg':'使用send返回的,给connect事件'})

        #告诉在线用户,现在在线的用户情况
        online_users = [name_ for name_, dic in USER.items()]
        emit('connect',online_users,broadcast=True)

    def on_disconnect(self):
        sid = request.sid
        print('disconnect,','sid=',sid)
        del_name = False
        for name,dic in USER.items():
            if sid == dic.get('sid'):
                del_name = name
                break
        if del_name:
            USER.pop(del_name)
        print(USER,'当前用户消息')
        online_users = [name_ for name_, dic in USER.items()]
        emit('disconnect', {'leave':del_name,'online_users':online_users}, broadcast=True)

    def on_single_chat(self,data):
        name = data.get('name') #接收消息的用户
        msg = data.get('msg') #消息
        sendName = data.get('sendName') #发送消息的用户
        sid_dic = USER.get(name)
        if sid_dic:
            #给该用户发送消息
            emit('single_chat',{'name':sendName,'msg':msg},to=sid_dic.get('sid'))
            #告诉发送方,消息发送成功
            emit('success',{'code':200,'msg':msg,'name':name})
            print(name,'用户在线,可以发送')
        else:
            #告诉发送方,消息发送失败
            emit('success',{'code':400,'msg':'该用户不在线,无法发送消息'})
            print(name, '用户不在线,不可以发送')

socketio.on_namespace(SingleChat('/single/chat'))


if __name__ == '__main__':
    socketio.run(app,debug=True)

   

2.3、single.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>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">
        const data = {{ data|tojson }};
        const name = data.name; // 当前用户名
        //1、发起连接
        const socket = io('http://'+document.domain+':'+location.port+'/single/chat',
            {query:{'token':'123456','name':name}}
        );


        //2、监听connect事件,
        socket.on('connect',function (data) {
            console.log(data);
            const showDiv = $('#showDataId');
            if (data){
                //将当前用户的名字删除
                for (let i = data.length - 1; i >= 0; i--) {
                    if (data[i] === name) {
                      data.splice(i, 1);
                    }
                  }
                //展示在线的用户名
                if(data.length>=1){
                    const pElement = $('<p>').text('[公告]在线的用户:'+data);
                    //添加到展示的div标签中
                    showDiv.append(pElement);
                }else{
                    const pElement = $('<p>').text('[公告] 当前只有您在线...');
                    //添加到展示的div标签中
                    showDiv.append(pElement);
                }
            }
        });

        // 3、监听disconnect事件,展示退出的用户消息,通知其他人
        socket.on('disconnect',function (dic) {
            const showDiv = $('#showDataId');
            const data = dic.online_users;
            const leave = dic.leave;
            if (data){
                //将当前用户的名字删除
                for (let i = data.length - 1; i >= 0; i--) {
                    if (data[i] === name) {
                      data.splice(i, 1);
                    }
                  }
                // 1、展示谁离线了
                const pElement = $('<p>').text('[公告] '+leave+'离线了...');
                //添加到展示的div标签中
                showDiv.append(pElement);

                //2、展示还在线的用户
                if(data.length>=1){
                    const pElement = $('<p>').text('[公告]在线的用户:'+data);
                    //添加到展示的div标签中
                    showDiv.append(pElement);
                }else{
                    const pElement = $('<p>').text('[公告] 当前只有您在线...');
                    //添加到展示的div标签中
                    showDiv.append(pElement);
                }
            }

        });

        //4、监听单聊事件,single_chat
        socket.on('single_chat',function (data) {
            const sendName = data.name;
            const msg = data.msg;
            const showDiv = $('#showDataId');
            //展示别人发送的消息
            if(sendName===name){

            }else {
                const pElement = $('<p>').text(sendName+'>'+msg);
                //添加到展示的div标签中
                showDiv.append(pElement);
            }
        })

        //5、监听消息发送是否成功,失败时要展示
        socket.on('success',function (data) {
            const code = data.code;
            const msg = data.msg;
            const name = data.name;
            const showDiv = $('#showDataId');
            if (code===200){
                const pElement = $('<p>').text('you to('+name+') >'+msg);
                //添加到展示的div标签中
                showDiv.append(pElement);
            }else {
               alert(msg)
            }
        })


        //6、发送消息
        function sendMsg() {
            const recvName = $('#recvUserId').val();
            const msg = $('#inputDataId').val();
            socket.emit('single_chat',{'name':recvName,'msg':msg,'sendName':name})
        }

    </script>
</head>
<body>
<div id="showDataId">

</div>
<div>
    <p>
        <input type="text" id="recvUserId" value="接收用户">
        <input type="text" id="inputDataId" value="消息">
        <input type="button" id="submitId" value="发送消息" onclick="sendMsg()">
    </p>

</div>

</body>
</html>

 三、代码测试

1、开启三个浏览器标签,分别输入

http://127.0.0.1:5000/single/chat?name=lhz

http://127.0.0.1:5000/single/chat?name=zzh

http://127.0.0.1:5000/single/chat?name=yf

2、两两之间互发消息

3、关闭lhz的浏览器标签

4、关闭zzh的浏览器标签

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1030948.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

脑电相关临床试验及数据分析01

临床试验设计01–04 作为一个医疗器械公司的开发–>算法–>项目–>产品&#xff0c;还是想在这里记录一下工作。 直接开始吧 临床试验的设计&#xff0c;主要分为20个部分&#xff0c;分别是 封面 一、申办者信息 二、所有临床试验机构和研究者列表 三、临床试验的…

基础算法--位运算

位运算理解&#xff1a; n >> k&#xff1a;代表n右移k位 比如 000011 >> 1 000001 前面会补零&#xff08;所以第几位是从0开始计算&#xff09; n & 1&#xff1a;表示最后一位是否为1 比如&#xff1a;n 3 0011 而 1 0001 则3 & 1 0011 & 000…

本地Docker Registry远程连接,为你带来高效便捷的镜像管理体验!

Linux 本地 Docker Registry本地镜像仓库远程连接 文章目录 Linux 本地 Docker Registry本地镜像仓库远程连接1. 部署Docker Registry2. 本地测试推送镜像3. Linux 安装cpolar4. 配置Docker Registry公网访问地址5. 公网远程推送Docker Registry6. 固定Docker Registry公网地址…

多输入多输出 | MATLAB实现LSSVM最小二乘支持向量机多输入多输出

多输入多输出 | MATLAB实现LSSVM最小二乘支持向量机多输入多输出 目录 多输入多输出 | MATLAB实现LSSVM最小二乘支持向量机多输入多输出预测效果基本介绍程序设计往期精彩参考资料 预测效果 基本介绍 MATLAB实现LSSVM最小二乘支持向量机多输入多输出 1.data为数据集&#xff0c…

Python 判断三位水仙花数

"""判断是否为三位水仙花数知识点&#xff1a;0、水仙花满足条件&#xff1a;(1 ** 3) (5 ** 3) (3 ** 3) 1531、字符串索引&#xff0c;例如&#xff1a;name zhouhua name[0] z2、变量类型转换函数3、双目运算符幂**,例如&#xff1a;3 ** 2 3 * 3 94、…

【Tricks】关于如何防止edge浏览器偷取chrome浏览器的账号

《关于如何防止edge浏览器偷取chrome浏览器的账号》 前段时间edge自动更新了&#xff0c;我并没有太在意界面的问题。但是由于我使用同一个网站平台时&#xff0c;例如b站&#xff0c;甚至是邮箱&#xff0c;edge的账号和chrome的账号会自动同步&#xff0c;这就导致我很难短时…

Linux su sudo命令

1、su命令——切换用户 1.1、切换到root用户(需要密码) su - root 1.2、切换到其他用户&#xff0c;比如jackma&#xff08;无需密码&#xff09; su - jackma 2、sudo命令——给普通用户添加root权限 2.1、用法 切换到root用户&#xff0c;执行visudo命令&#xff0c;会自动…

Leetcode 951. 翻转等价二叉树

文章目录 题目代码&#xff08;9.22 首刷部分看解析&#xff09; 题目 Leetcode 951. 翻转等价二叉树 代码&#xff08;9.22 首刷部分看解析&#xff09; class Solution { public:bool flipEquiv(TreeNode* root1, TreeNode* root2) {if(!root1 && !root2)return tr…

AI也需要透明度?是的,需要

文章目录 什么是AI透明度为什么需要AI透明度AI透明度的弱点如何做好AI透明度推荐阅读 什么是AI透明度 AI透明度指的是人工智能&#xff08;AI&#xff09;系统的工作原理和决策过程能够被理解、解释和追踪的程度。它包括以下几个方面&#xff1a; 可解释性&#xff08;Explai…

安装nvm 切换不同nodejs版本号

1.下载nvm:NVM下载 - NVM中文网 2.卸载node&#xff08;没有安装的可以直接跳过&#xff09; 3.安装 nvm list available 查看可安装的node版本nvm install 12.16.0 安装指定版本node nvm ls 查看已安装的node版本nvm use 16.13.0 切换…

第二证券:个人开证券账户要开户费吗?

随着互联网和移动端东西的遍及&#xff0c;越来越多的人开端涉足股票投资&#xff0c;开立证券账户也成为一个热门话题。但是&#xff0c;许多初学者或许会有疑问&#xff0c;个人开证券账户是否需求支付开户费呢&#xff1f;这个问题的答案并不是那么简略&#xff0c;需求考虑…

使用企业订货系统的原因和考虑|网上APP订单管理软件

使用企业订货系统的原因和考虑|网上APP订单管理软件 企业要用订货系统主要如下原因&#xff1a; 第一、在线订货系统能让销售即时看到商品信息。商品售价多少&#xff0c;进货价多少&#xff0c;上次跟客户的成交价是多少&#xff0c;最低可以卖多少钱&#xff0c;用个本子记录…

【论文阅读 05】图像异常检测研究现状综述

1 图像异常检测任务 图像异常检测任务根据异常的形态可以分为定性异常的分类和定量异常的定位两个类别. 定性异常的分类&#xff1a;整体地给出是否异常的判断&#xff0c;无需准确定位异常的位置。 如图2左上图所示, 左侧代表正常图像, 右侧代表异常图像, 在第1行中,模…

【一、虚拟机vmware安装】

安装虚拟机 下载 官方下载地址&#xff1a;https://www.vmware.com/cn.html 大概流程就是&#xff0c;最重要的事最后一步

YashanDB混合存储揭秘:行式存储如何为高效TP业务保驾护航(下)

上一篇文章https://mp.weixin.qq.com/s/mQLzi2PSZxqwwACSsq49ng为大家讲述了行式存储中事务并发控制的关键设计和优化。YashanDB采用了In-place Update 的块级 MVCC&#xff0c;能极大提高事务并发处理能力。本篇文章&#xff0c;我们将会详解插入性能优化和宽行存储的设计。 插…

夏日漫步(BFS)-- 2023百度之星初赛第二场

码蹄集 --原题链接 解析&#xff1a; BFS&#xff0c;每次只能前后&#xff0c;或者瞬移&#xff0c;并且每次消耗都为1&#xff0c;所以宽搜即可。 #include<bits/stdc.h> using namespace std; const int N2e55; int n,a[N],ne[N]; int vis[N],res; map<int,int>…

四、二叉树-上(Binary tree)

文章目录 一、算法核心思想二、算法模型&#xff08;一&#xff09;回溯1.[104.二叉树的最大深度](https://leetcode.cn/problems/maximum-depth-of-binary-tree/)&#xff08;1&#xff09;思路&#xff08;2&#xff09;代码&#xff08;3&#xff09;复杂度分析 2.[144.二叉…

Blender导出FBX给UE5

最近在学习UE5的资源导入&#xff0c;总结如下&#xff1a; 建模使用Blender&#xff0c;UE5版本是5.3 1.纯静态模型导入UE5 Blender FBX导出设置保持默认即可&#xff0c; UE5把导入设置里Miscellaneous下Force Front XAxis和Convert Scene Unit勾选即可 2.带骨骼动画的模型…

蔡司光学公益助童行动,以爱共创美好“视”界

2023年是蔡司光学坚持初心&#xff0c;号召视光行业与全社会关爱乡村学童视力健康的第十年&#xff0c;也是蔡司光学带领视光同行一起跋山涉水、走遍全国多地乡村学校&#xff0c;践行宗旨的第十年。点滴善意&#xff0c;汇聚成光。过去这十年间&#xff0c;蔡司光学一直在路上…

在uniapp中使用 秋云ucharts图表,运行到小程序

步骤一&#xff1a;通过使用 HBuilderX 直接导入项目&#xff08;uni_modules 版本&#xff09; 步骤二&#xff1a;在uCharts官网 - 秋云uCharts跨平台图表库 演示中&#xff0c;先弄个demo试着运行&#xff0c; 步骤三&#xff1a;查看自己需要的配置&#xff0c; 下面是我的…