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

发布于:2024-12-19 ⋅ 阅读:(10) ⋅ 点赞:(0)

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

实验环境

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/ 开启愉快的自我交流吧

另可参考点击进入


网站公告

今日签到

点亮在社区的每一天
去签到