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

一、概述和项目结构

在使用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_roomapp = 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.sidprint('disconnect,','sid=',sid)del_name = Falsefor name,dic in USER.items():if sid == dic.get('sid'):del_name = namebreakif 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_chatsocket.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.xdnf.cn/news/138975.html

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

相关文章

leetcode543 二叉树的直径

题目 给你一棵二叉树的根节点&#xff0c;返回该树的 直径 。 二叉树的 直径 是指树中任意两个节点之间最长路径的 长度 。这条路径可能经过也可能不经过根节点 root 。 两节点之间路径的 长度 由它们之间边数表示。 示例 输入&#xff1a;root [1,2,3,4,5] 输出&#xff1…

jmeterbeanshell调用jsonpath获取对应值

1.jmeter 新建线程组、Java Request、BeanShell Assertion、View Results Tree 2、在BeanShell Assertion中贴入代码&#xff1a; import org.apache.jmeter.extractor.json.jsonpath.JSONManager; import java.util.List; JSONManager js new JSONManager(); String jsonStr…

手机上比较好用的笔记软件使用哪一款?

手机已经成为我们日常生活不可或缺的一部分&#xff0c;它们伴随着我们的方方面面。在这部小小的设备中&#xff0c;我们可以完成许多任务&#xff0c;其中之一就是记录笔记。手机上的笔记软件如今多种多样&#xff0c;但在选择时&#xff0c;敬业签可能是你不容错过的选择。 …

多平台兼容性:跑腿系统开发的移动端和Web端技术选项

随着移动设备和Web浏览器的广泛使用&#xff0c;跑腿系统的开发需要考虑多平台兼容性。本文将讨论一些在开发跑腿系统的移动端和Web端时可用的技术选项&#xff0c;并提供示例代码以帮助您入门。 移动端技术选项&#xff1a; 1. React Native React Native是一个流行的移动应…

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

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

查看吾托帮88.47的docker里的tomcat日志

步骤如下 &#xff08;1&#xff09;ssh &#xff08;2&#xff09;ssh root192.168.88.47 等待输入密码&#xff1a;fytest &#xff08;3&#xff09;pwd #注释&#xff1a;输出/root &#xff08;4&#xff09;docker exec -it wetoband_deploy /bin/bash #注释&#xff1…

【记录】Python 之于 C/C++ 区别

记录本人在 Python 上经常写错的一些地方&#xff08;C/C 写多了&#xff0c;再写 Python 有点切换不过来&#xff09; 逻辑判断符号用 and、or、!可以直接 10 < num < 30 比较大小分支语句&#xff1a;if、elif、else使用 、-&#xff0c;Python 中不支持 、- - 这两个…

elk日志某个时间节点突然搜索不到了

elk日志某个时间节点突然搜索不到了,检查filebeat正常 Kibana手动上传数据: 响应: Error: Validation Failed: 1: this action would add [2] total shards, but this cluster currently has [2000]/[2000] maximum shards open 原因:ElasticSearch总分片数量导致的异常,ES…

Qt重写QTreeWidget实现拖拽

介绍 此文章记录QTreeWidget的重写进度&#xff0c;暂时停滞使用&#xff0c;重写了QTreeWidget的拖拽功能&#xff0c;和绘制功能&#xff0c;自定义了数据结构&#xff0c;增加复制&#xff0c;粘贴&#xff0c;删除&#xff0c;准备实现动态刷新数据支持千万数据动态刷新&a…

JAVA面经整理(2)

一)解决哈希冲突的方法有哪些&#xff1f; 哈希冲突指的是在哈希表中&#xff0c;不同的键值映射到了相同的哈希桶&#xff0c;也就是数组索引&#xff0c;导致键值对的冲突 1)设立合适的哈希函数:通过哈希函数计算出来的地址要均匀的分布在整个空间中 2)负载因子调节: 2.1)开放…

【vue】vue+easyPlayer 实现宫格布局及视频播放

由于业务需要&#xff0c;ant-design-vue框架集成easyPlayer.js作为视频播放器。EasyPlayer.js H5播放器&#xff0c;是一款能够同时支持HTTP、HTTP-FLV、HLS&#xff08;m3u8&#xff09;、WS视频直播与视频点播等多种协议&#xff0c;支持H.264、H.265、AAC等多种音视频编码格…

王江涛十天搞定考研词汇

学习目标&#xff1a; 考研词汇 学习内容&#xff1a; 2023-9-17 第一天考研词汇 学习时间&#xff1a; 开始:2023-9-17 结束:进行中 学习产出&#xff1a; 2023-9-17intellect智力&#xff1b;知识分子intellectual智力的&#xff1b;聪明的intellectualize使...理智化&a…

堆的实现(C版)

普通的二叉树是不适合用数组来存储的&#xff0c;因为可能会存在大量的空间浪费。而完全二叉树更适合使用顺序结构存储。现实中我们通常把堆(一种二叉树)使用顺序结构的数组来存储&#xff0c;需要注意的是这里的堆和操作系统虚拟进程地址空间中的堆是两回事&#xff0c;一个是…

软件设计模式系列之十二——外观模式

在软件设计中&#xff0c;经常会遇到需要与复杂子系统进行交互的情况。为了简化客户端与子系统之间的交互&#xff0c;提高系统的可维护性和可用性&#xff0c;外观模式应运而生。外观模式&#xff08;Facade Pattern&#xff09;是一种结构型设计模式&#xff0c;它提供一个统…

激活函数总结(四十一):激活函数补充(ShiLU、ReLUN)

激活函数总结&#xff08;四十一&#xff09;&#xff1a;激活函数补充 1 引言2 激活函数2.1 ShiLU激活函数2.2 ReLUN激活函数 3. 总结 1 引言 在前面的文章中已经介绍了介绍了一系列激活函数 (Sigmoid、Tanh、ReLU、Leaky ReLU、PReLU、Swish、ELU、SELU、GELU、Softmax、Sof…

腾讯云16核服务器性能测评_轻量和CVM配置大全

腾讯云16核服务器配置大全&#xff0c;CVM云服务器可选择标准型S6、标准型SA3、计算型C6或标准型S5等&#xff0c;目前标准型S5云服务器有优惠活动&#xff0c;性价比高&#xff0c;计算型C6云服务器16核性能更高&#xff0c;轻量16核32G28M带宽优惠价3468元15个月&#xff0c;…

简单的手机电脑无线传输方案@固定android生成ftp的IP地址(android@windows)

文章目录 abstractwindows浏览android文件环境准备客户端软件无线网络链接步骤其他方法 手机浏览电脑文件公网局域网everythingpython http.server 高级:固定android设备IP准备检查模块是否生效 windows 访问ftp服务器快捷方式命令行方式双击启动方式普通快捷方式映射新的网络位…

第六次面试、第一次复试

第六面&#xff1a; hr迟到&#xff0c;说是搞错了以为线下&#xff0c;我打电话过去才开始&#xff0c;问我想电话面还是视频&#xff0c;果断电话面 自我介绍 介绍了一下公司的工作 ................. 项目拷打&#xff1a; grpc数据如何传输的如何调用两个接口如何获取…

Android 12 源码分析 —— 应用层 六(StatusBar的UI创建和初始化)

Android 12 源码分析 —— 应用层 六&#xff08;StatusBar的UI创建和初始化) 在前面的文章中,我们分别介绍了Layout整体布局,以及StatusBar类的初始化.前者介绍了整体上面的布局,后者介绍了三大窗口的创建的入口处,以及需要做的准备工作.现在我们分别来细化三大窗口的UI创建和…

利用大模型知识图谱技术,告别繁重文案,实现非结构化数据高效管理

我&#xff0c;作为一名产品经理&#xff0c;对文案工作可以说是又爱又恨&#xff0c;爱的是文档作为嘴替&#xff0c;可以事事展开揉碎讲清道明&#xff1b;恨的是只有一个脑子一双手&#xff0c;想一边澄清需求一边推广宣传一边发布版本一边申报认证实在是分身乏术&#xff0…