flask_socketio 以继承 Namespace方式实现一个网页聊天应用

点击进入上一篇,可作为参考

实验环境

python 用的是3.11.11
其他环境可以通过这种方式一键安装:
pip install flask==3.1.0 Flask-SocketIO==5.4.1 gevent-websocket==0.10.1 -i https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple
pip list 详情如下:
Package          Version
---------------- -------
bidict           0.23.1
blinker          1.9.0
click            8.1.7
Flask            3.1.0
Flask-SocketIO   5.4.1
gevent           24.11.1
gevent-websocket 0.10.1
greenlet         3.1.1
h11              0.14.0
itsdangerous     2.2.0
Jinja2           3.1.4
MarkupSafe       3.0.2
pip              24.2
python-engineio  4.11.1
python-socketio  5.11.4
setuptools       75.1.0
simple-websocket 1.1.0
Werkzeug         3.1.3
wheel            0.44.0
wsproto          1.2.0
zope.event       5.0
zope.interface   7.2

先看效果:

在这里插入图片描述

目录结构:

在这里插入图片描述

app2.py中的内容如下:

from flask import Flask, render_template, request 
from flask_socketio import SocketIO, Namespace, join_room, leave_room  

app = Flask(__name__)  
app.config['SECRET_KEY'] = 'secret!'  

def create_application(name, config=None, timeout=60, proxy=None):
    app = Flask(name)
    @app.route("/", methods=["GET", "POST"])
    def main():
        return render_template("index.html")
    return app

class MyNamespace(Namespace):  
    def on_connect(self):  
        print("Client connected")  


    # def on_message(self, message):  
    #     print(f"Received message: {message}")  
    #     # socket_io.emit('response', {'data': 'Message received'}, namespace="/my_room") # 下边这种方式和本行这个方式都可以(在没有to传递参数时,self方式不能传递to这个参数)
    #     self.emit('response', {'data': 'Message received'}, namespace="/my_room")
    
    def on_joinRoom(self, message):
        # global Room  # 没有被用到吧,应该没啥用
        # print(message)
        join_room(message['room'])  #加入房间有专门的函数,不用我们管

        # socket_io.emit("room_joined", {
        socket_io.emit("roomJoined", {
            "user" : request.sid,
            "room" : message['room']
        },to=message['room'], namespace="/my_room")  # !!!这个namespace="/my_room"一定要写
    
    def on_sendMsg(self,message):
        print(message)
        # 下边这个emit中的“SendtoAll”是 前端socket.on('SendtoAll')的监听对象   to=message['room'] 表示给房间里的所有人都发送消息  如果不写则表示个自己一个人回消息
        # request.sid貌似是每对socket连接都会不一样,但是没断开的应该是一样的
        
        # self.emit 这个不能传递, to=message["room"] 不然会报错
        # self.emit('SendtoAll', {"msg":message["msg"], "user":request.sid}, to=message["room"], namespace="/my_room")
        socket_io.emit('SendtoAll', {"msg":message["msg"], "user":request.sid}, to=message["room"], namespace="/my_room")
    
    def on_leaveRoom(self,message):
        print(message)
        socket_io.emit('roomLeftPersonal', {"room": message['room'], "user": request.sid}, namespace="/my_room")  # 这个没写to=message['room'] 表示给自己一个人回消息
        leave_room(message['room'])  # 可神奇,他咋知道那个人离开了,可能是socket连接所以知道
        socket_io.emit('roomLeft', {"room":message['room'], "user":request.sid}, to=message['room'], namespace="/my_room")

        
app = create_application("pipeagent_service", config=None)
socket_io = SocketIO(app, processes=True, cors_allowed_origins="*", async_mode='gevent')
socket_io.on_namespace(MyNamespace('/my_room'))
if __name__ == "__main__":
    socket_io.run(app=app, host="0.0.0.0", debug=False, log_output=True)

index.html中的内容如下:

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>flask socketio通信</title>
<!--        flask-socketio-->
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js" integrity="sha512-bLT0Qm9VnAYZDflyKcBaQ2gg0hSYNQrJ8RilYldYQ1FxQYoCLtUjuuRuZo+fjqhx/qtq/1itJ0C2ejDxltZVFg==" crossorigin="anonymous"></script>

<!--        Jquery-->
        <!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.js"></script> -->
        <script type="text/javascript" src="//cdn.bootcss.com/socket.io/3.1.2/socket.io.min.js"></script>
        <script type="text/javascript" src="{{url_for('static', filename='js/index.js')}}"></script>
    </head>
    <body>

        <h3>Join Room</h3>
        <form id="joinRoom" method="POST" action="#">
            <label>Room Number</label>
            <input type="text" id="roomNum" required>
            <input type="submit" id="submitRoomNum">

        </form>
        <button id="leave_room">Leave</button>

        <h1>Hello World</h1>
    <ul id="chatContent">
        <li>Text</li>
    </ul>
    <form id="SubmitForm" method="POST" action="#">
        <h3>发送文字</h3>
        <textarea placeholder="输入文字" name="msg" id="chatMsg" required></textarea>

        <button type="submit">发送</button>
    </form>
    </body>
</html>

index.js中的内容如下:

$(document).ready(function(){
    // 这个 my_room对应后端中的Namespace 即命名空间
    var socket = io.connect('http://localhost:5000/my_room');  
    socket.on('connect', function() { 
        socket.send('Client Connected') 
        // console.log("Connected to server");  
    }); 
    
    $('form#joinRoom').submit(function (event){
        socket.emit('joinRoom', {room:$('#roomNum').val()})
        return false
    });
    // 3
    socket.on('roomJoined', function (msg, cb) {
        $('#chatContent').append('<li>' + msg.user + 'has joined room'+ msg.room +' </li>')
    });
    // 4
    $('form#SubmitForm').submit(function (event){
        // 发送给后端的sendMsg方法
        socket.emit('sendMsg', {
            msg:$('#chatMsg').val(),
            room:$('#roomNum').val()
        });
        $('#chatMsg').val("");
        return false
    });

    // 5 监听后端的SendtoAll方法
    socket.on('SendtoAll', function (msg, cb) {
        $('#chatContent').append('<li>' + msg.user + ': ' + msg.msg + '</li>')
    });
    // 6
    $('#leave_room').on('click', function (){
        socket.emit('leaveRoom', {room:$('#roomNum').val()})
        console.log("sent")
    });
    // 7
    socket.on('roomLeftPersonal', function (msg, cb) {
        $('#chatContent').append('<li>' + 'you have left room'+ msg.room +' </li>')

    });
    // 8 
    socket.on('roomLeft', function (msg, cb) {
        $('#chatContent').append('<li>' + msg.user + 'has left room'+ msg.room +' </li>')

    });
    // socket.on('response', function(data) {  
    //     console.log(data.data);  
    // });  
    // socket.on('disconnect', function() {  
    //     console.log('Disconnected');  
    // });  
    // socket.emit('message', 'Hello, server!');



    // 1  一般的执行步骤 1,2,3....
    // var socket = io();
    //  连接socket
    // socket.on('connect', function (){
    //     socket.send('Client Connected')
    // });
})

运行:即 python app2.py 然后打开两个网页,并分别输入http://127.0.0.1:5000/ 开启愉快的自我交流吧

另可参考点击进入

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

笔记本重装系统教程【详细教程】

一、装机前说明 各位有装机需求的伙伴&#xff0c;请根据自己的电脑配置选择合适操作系统&#xff0c;可以实现自己装机的伙伴&#xff0c;相信大家这点可以确认好。 ———————————————————————— 我的配置&#xff1a; 我的电脑是联想拯救者lenovoY7000…

uniapp入门 01创建项目模版

0安装 hbuilder x 标准版 1.创建模版工程 2.创建官方 案例工程 index.uvuewen 文件解析 <!-- 模版 标签 --> <template><view></view></template><!-- 脚本 --> <script>export default {data() {return {}},onLoad() {},methods:…

ARCGIS国土超级工具集1.2更新说明

ARCGIS国土超级工具集V1.2版本&#xff0c;功能已增加至47 个。在V1.1的基础上修复了若干使用时发现的BUG&#xff0c;新增了"矢量分割工具"菜单&#xff0c;同时增加及更新了了若干功能&#xff0c;新工具使用说明如下&#xff1a; 一、勘测定界工具栏更新界址点成果…

Vue3源码笔记阅读1——Ref响应式原理

本专栏主要用于记录自己的阅读源码的过程,希望能够加深自己学习印象,也欢迎读者可以帮忙完善。接下来每一篇都会从定义、运用两个层面来进行解析 定义 运用 例子:模板中访问ref(1) <template><div>{{str}}</div> </template> <script> impo…

[react] 优雅解决typescript动态获取redux仓库的类型问题

store.getState()是可以获取总仓库的 先拿到函数的类型 再用ReturnType<T> 它是 TypeScript 中的一个内置条件类型&#xff0c;用于获取某个函数类型 T 的返回值类型 代码 // 先拿总仓库的函数类型type StatefuncType typeof store.getState;//再拿函数类型T的返回值类…

【Qt】QWidget中的常见属性及其功能(一)

目录 一、 enabled 例子&#xff1a; 二、geometry 例子&#xff1a; window fram 例子 &#xff1a; 四、windowTiltle 五、windowIcon 例子&#xff1a; qrc机制 创建qrc文件 例子&#xff1a; qt中的很多内置类都是继承自QWidget的&#xff0c;因此熟悉QWidget的…

R语言的字符串操作

【图书推荐】《R语言医学数据分析实践》-CSDN博客 《R语言医学数据分析实践 李丹 宋立桓 蔡伟祺 清华大学出版社9787302673484》【摘要 书评 试读】- 京东图书 (jd.com) R语言医学数据分析实践-R语言的数据结构-CSDN博客 在R语言中&#xff0c;字符串是一种表示文本数据的数…

webGL硬核知识:图形渲染管渲染流程,各个阶段对应的API调用方式

一、图形渲染管线基础流程概述 WebGL 的图形渲染管线大致可分为以下几个主要阶段&#xff0c;每个阶段都有其特定的任务&#xff0c;协同工作将 3D 场景中的物体最终转换为屏幕上呈现的 2D 图像&#xff1a; 顶点处理&#xff08;Vertex Processing&#xff09;阶段&#xff1…

《深入浅出Apache Spark》系列⑤:Spark SQL的表达式优化

导读&#xff1a;随着数据量的快速增长&#xff0c;传统的数据处理方法难以满足对计算速度、资源利用率以及查询响应时间的要求。为了应对这些挑战&#xff0c;Spark SQL 引入了多种优化技术&#xff0c;以提高查询效率&#xff0c;降低计算开销。本文从表达式层面探讨了 Spark…

创建项目以及本地仓库和远程仓库并上传项目

创建项目以及本地仓库和远程仓库并上传项目 其详细流程如下&#xff1a; 1、本地创建项目 2、创建本地仓库&#xff08;若使用idea在创建项目时选择了创建.git本地仓库&#xff0c;则此步骤省略&#xff09; 进入到你需要上传的项目的目录下&#xff0c;右键找到Git Bah He…

快速解决oracle 11g中exp无法导出空表的问题

在一些生产系统中&#xff0c;有些时候我们为了进行oracle数据库部分数据的备份和迁移&#xff0c;会使用exp进行数据的导出。但在实际导出的时候&#xff0c;我们发现导出的时候&#xff0c;发现很多空表未进行导出。今天我们给出一个快速解决该问题的办法。 一、问题复现 我…

MySQL八股-MVCC入门

文章目录 当前读&#xff08;加锁&#xff09;快照读&#xff08;不加锁&#xff09;MVCC隐藏字段undo-log版本链A. 第一步B.第二步C. 第三步 readview MVCC原理分析RCA. 先来看第一次快照读具体的读取过程&#xff1a;B. 再来看第二次快照读具体的读取过程: RR隔离级别 当前读…

【已解决】启动此实时调试器时未使用必需的安全权限。要调试该进程,必须以管理员身份运行此实时调试器。是否调试该进程?

【已解决】启动此实时调试器时未使用必需的安全权限。要调试该进程&#xff0c;必须以管理员身份运行此实时调试器。是否调试该进程? 目录一、前言二、具体原因三、解决方法 目录 报错截图 一、前言 进行应用程序开发时&#xff0c;需要对w3wp进行附加调试等场景&#xff…

基于Qt的登陆界面设计

目标 自由发挥登录界面的应用场景&#xff0c;实现一个登录窗口的界面。 要求&#xff1a;每行代码都要有注释 代码 // 设置窗口大小为600x400像素 this->resize(600,400); // 设置窗口标题为"TheWitcher 巫师3&#xff1a;狂猎" this->setWindowTitle(&qu…

Elasticsearch 8.x 集成与 Java API 使用指南

目录 背景 版本区别 安装elaticsearch8.x服务 启动es服务 安装es管理平台 项目集成 pom.xml文件引入依赖 application.yml配置 ES初始化配置类实现 ES8.x常用API实现 1.判断es索引是否存在 2.删除索引 3.创建索引 4.新增文档 5.更新文档 6.根据id查询文档 7.根…

EfficientNet模型Pytorch版本具体实现

EfficientNet模型原理&#xff1a;EfficientNet&#xff1a;对模型深度、宽度和分辨率的混合缩放策略-CSDN博客 一、激活函数&#xff1a; EfficientNet模型使用了Swish激活函数而不是更常见的Relu激活函数 1、公式定义 Swish(x) x * sigmoid(x)是一个平滑的非线性激活函数…

Git连接远程仓库(超详细)

目录 一、Gitee 远程仓库连接 1. HTTPS 方式 2. SSH公钥方式 &#xff08;1&#xff09;账户公钥 &#xff08;2&#xff09;仓库公钥 仓库的 SSH Key 和账户 SSH Key 的区别&#xff1f;​ 二、GitHub远程仓库连接 1. HTTPS方式 2.SSH公钥方式 本文将介绍如何通过 H…

AutoMQ 流表一体新特性 Table Topic 发布: 无缝集成 AWS S3 Table 和 Iceberg

超越共享存储&#xff1a;使用 Apache Iceberg 中的 AutoMQ Table Topic 实现流处理与分析的统一 自 2023 年底官宣以来&#xff0c;AutoMQ 成功地将 Apache Kafka 从“Shared Nothing architecture”转变为“Shared Storage architecture”&#xff0c;这为京东、知乎、小红书…

Upload-labs 靶场(通关攻略)

WebShell 一句话木马: <?php eval($_POST[a])?> <?php system($_POST[a])?> 第一关&#xff08;删除前端js校验&#xff09; 删除return checkFile() 就能上传成功 第二关(抓包文件类型校验) BP抓包修改后缀 改为2.php后放行 第三关(上传php同种类型的不…

Linux —— 管理进程

一、查看进程 运行态&#xff08;Running&#xff09; 定义&#xff1a;处于运行态的进程正在 CPU 上执行指令。在单 CPU 系统中&#xff0c;同一时刻只有一个进程处于运行态&#xff1b;在多 CPU 或多核系统中&#xff0c;可能有多个进程同时处于运行态。示例&#xff1a; 当…