• Flask学习Ⅳ


    Websocket

    1.轮询:

    • HTTP协议的轮询(无状态) TCP三次握手
    • 缺陷:
      • 信息不能及时传达
      • 客户端和服务器都浪费很多的资源
      • HTTP无法跟踪定位客户端

    2.长轮询:

    • HTTP协议的长轮询
    • 可能出现: HTTP请求超时, HTTP请求断开
    • 缺陷:
      • 消息实时性不高
      • 占用资源
      • 客户端线程资源占用

    3.长连接:

    • 优点:
      • 消息及时
      • 一次连接不会断开
    • 缺陷:
      • 占用空间小了,CPU和内存消耗大

    Flask建立长连接

    1.准备阶段

    • Web - Socket
    • pip install gevent-websocket

    2.基本流程

    from geventwebsocket.handler import WebSocketHandler	#ws协议处理
    from geventwebsocket.server import WSGIServer	#替换Flask原有的WSGI
    from geventwebsocket.websocket import WebSocket	#语法提示(非必须)
    
    from flask import Flask
    
    app = Flask(__name__)
    
    if __name__ == '__main__':
       http_server = WSGIServer(("0.0.0.0", 9527), app, handler_class=WebSocketHandler)	#监听ip和port,app,ws协议处理
       http_server.serve_forever()
    

    Flask+WebSocket创建一个简易的web聊天室

    群聊室

    • py文件
    from geventwebsocket.handler import WebSocketHandler
    from geventwebsocket.server import WSGIServer
    from geventwebsocket.websocket import WebSocket
    
    from flask import Flask, request
    
    app = Flask(__name__)
    
    client_list = []
    
    @app.route("/ws")
    def ws():
        sock = request.environ.get("wsgi.websocket")  # type:WebSocket
        client_list.append(sock)
        print(client_list)
        while 1:
            try:
                msg = sock.receive()    # 检查连接连接是否异常
            except:
                client_list.remove(sock)	# 连接异常则从连接列表中删除该socket
                break
            for client in client_list:
                if client == sock:
                    continue
                try:
                    client.send(msg)	# 检查信息是否成功发出,若无这说明该连接已经断开
                except:
                    continue
    
        return "200 OK"
    
    if __name__ == '__main__':
        http_server = WSGIServer(("0.0.0.0", 9527), app, handler_class=WebSocketHandler)  # environ对象交给app(flask)处理
        http_server.serve_forever()
    
    • html文件
    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>群聊室</title>
    </head>
    <body>
    <h1>欢迎进入群聊室!</h1>
    <input type="text" id="text"> <button id="send">点击发送</button>
    <div id="content_list"></div>
    </body>
    <script type="application/javascript">
        //新建ws连接
        var ws = new WebSocket("ws://127.0.0.1:9527/ws");
        //接收到消息生成p标签并展示在页面上
        ws.onmessage = function (eventMessage) {
            var msg = eventMessage.data;
            var p = document.createElement("p");
            p.innerText = msg;
            document.getElementById("content_list").appendChild(p);
        };
    	//在页面上输入消息并发送
        document.getElementById("send").onclick = function () {
            var msg = document.getElementById("text").value;
            ws.send(msg);
        }
    
    </script>
    </html>
    

    私聊室

    • py文件
    import json
    
    from geventwebsocket.handler import WebSocketHandler
    from geventwebsocket.server import WSGIServer
    from geventwebsocket.websocket import WebSocket
    
    from flask import Flask, request, render_template
    
    app = Flask(__name__)
    
    client_dict = {}	#改用字典,能显示发送消息人的用户名
    
    @app.route("/ws/<username>")	#动态参数获取用户名
    def ws(username):
        sock = request.environ.get("wsgi.websocket", None)   # type:WebSocket
        # 1.非ws协议上来的请求 None
        # 2.ws协议认证失败
        if not sock:
            return "请使用ws协议连接!"
        client_dict[username] = sock    # 用户名:socket套接字
        print(len(client_dict), client_dict)
    
        while 1:
            msg = sock.receive()
            msg_dict = json.loads(msg)
            recipient = msg_dict.get("recipient")   #找到接收方
            recipient_sock = client_dict.get(recipient)	#根据接收方,从client_dict拿出对应socket
            recipient_sock.send(msg)    #原封不动返回给接收方
    
    @app.route("/")
    def index():
        return render_template("chat.html")
    
    if __name__ == '__main__':
        http_server = WSGIServer(("0.0.0.0", 9527), app, handler_class=WebSocketHandler)
        http_server.serve_forever()
    
    • html文件
    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>聊天室</title>
    </head>
    <body>
    <h1>欢迎进入私聊室!</h1>
    用户名: <input type="text" id="username"> <button id="login">登入</button>
    
    <p>给 <input type="text" id="recipient"> 发送 <input type="text" id="text"> <button id="send">点击发送</button></p>
    
    <div id="content_list"></div>
    </body>
    <script type="application/javascript">
        var ws = null;
        document.getElementById("login").onclick = function () {
            //获取用户名作为动态参数传递给server端
            var username = document.getElementById("username").value;
            //修改ws连接
            ws = new WebSocket("ws://127.0.0.1:9527/ws/"+username);
            ws.onopen = function () {
                alert("欢迎登入聊天室!")
            };
            //接收消息并新建p标签显示在页面上
            ws.onmessage = function (eventMessage) {
                var msg = JSON.parse(eventMessage.data);
                console.log(msg)
                var p = document.createElement("p");
                p.innerText = msg.sender + ':' + msg.msg;
                document.getElementById("content_list").appendChild(p);
            };
        }
        //发送消息
        document.getElementById("send").onclick = function () {
            var msg = document.getElementById("text").value;
            var sender = document.getElementById("username").value;
            var recipient = document.getElementById("recipient").value;
            var detail = {
                "msg":msg,
                "sender":sender,
                "recipient":recipient
            };
            console.log(detail)
            ws.send(JSON.stringify(detail));    //object(字典)不能直接传输
        }
    
    </script>
    </html>
    
  • 相关阅读:
    前端-JavaScript
    前端-HTML
    Python源程序(.py)转换为可执行文件(.exe)
    进程
    算法之动态规划问题
    算法之斐波那契数列
    贪心算法找零问题
    算法之迷宫问题
    数据结构相关知识
    常用排序算法
  • 原文地址:https://www.cnblogs.com/straightup/p/13722407.html
Copyright © 2020-2023  润新知