zoukankan      html  css  js  c++  java
  • WebSocket 笔记

    WebSocket介绍

    - 菜鸟教程详解连接

    - 下载:pip install gevent-websocket

    - WebSocket 是一种协议;是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议;

    WebSocket 使得客户端和服务器之间的数据交换变得更加简单,
    允许服务端主动向客户端推送数据。
    
    在 WebSocket API 中,
    浏览器和服务器只需要完成一次握手,
    两者之间就直接可以创建持久性的连接,并进行双向数据传输。

    - 轮询:

    是在特定的的时间间隔(如每1秒),
    由浏览器对服务器发出HTTP请求,
    然后由服务器返回最新的数据给客户端的浏览器。
    
    
    传统轮询的缺点:
        浪费资源,
        服务器,客户端压力大

    - 长轮询:

    客户端向服务器发送Ajax请求,服务器接到请求后hold住连接,
    直到有新消息才返回响应信息并关闭连接,
    客户端处理完响应信息后再向服务器发送新的请求。 
    
    优点:在无消息的情况下不会频繁的请求,耗费资源小。 
    缺点:服务器hold连接会消耗资源,返回数据顺序无保证,难于管理维护。 
    实例:WebQQ、Hi网页版、Facebook IM。

    - WebScoket:

    浏览器通过 JavaScript 向服务器发出建立 WebSocket 连接的请求,
    连接建立以后,客户端和服务器端就可以通过 TCP 连接直接交换数据。
    
    当你获取 Web Socket 连接后,
    你可以通过 send() 方法来向服务器发送数据,
    并通过 onmessage 事件来接收服务器返回的数据。

    WebSocket+Flask开启一个WebSocket服务

    - 示例:

    from flask import Flask, request
    from geventwebsocket.handler import WebSocketHandler  # 开启WebSocket协议的服务
    from gevent.pywsgi import WSGIServer  # WSGI 支持多线程的 socket
    from geventwebsocket.websocket import WebSocket
    
    app = Flask(__name__)
    @app.route("/ws")
    def ws():
        # print(request.environ)  # 打印原始的 request
        # print(request.environ.get("wsgi.websocket"))  # 获取ws对象
        ws = request.environ.get("wsgi.websocket")  # type: WebSocket
        data = ws.receive()
        print(data)
        ws.send("发送消息给前端")
    
    if __name__ == '__main__':
        # 开启服务
        http_serv = WSGIServer(("0.0.0.0", 5000), app, handler_class=WebSocketHandler)
        http_serv.serve_forever()

      - 前端:

    <!DOCTYPE html>
    <html lang="en">
    <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</title>
    <body>
    <script>
        var ws = new WebSocket("ws://127.0.0.1:5000/we/" + username);
        ws.send("发送给客户端");
        ws.onmessage = function (data) {
            console.log(data.data);
        }
    </script>
    </body>
    </html>

    群聊小Demo

    - 视图:

    import json
    
    from flask import Flask, request, render_template
    from geventwebsocket.handler import WebSocketHandler
    from gevent.pywsgi import WSGIServer
    from geventwebsocket.websocket import WebSocket
    
    app = Flask(__name__)
    user_socket_list = []
    
    
    @app.route("/ws")
    def ws():
        # print(request.environ.get("wsgi.websocket"))
        user_web_socket = request.environ.get("wsgi.websocket")  # type: WebSocket
        user_socket_list.append(user_web_socket)
        while 1:
            try:
                data = user_web_socket.receive()
                print(data)
                for user_socket in user_socket_list:
                    if user_web_socket != user_socket:
                        user_socket.send(data)
            except:
                user_socket_list.remove(user_web_socket)
    
    
    @app.route("/chat")
    def chat():
        return render_template("ws.html")
    
    
    if __name__ == '__main__':
        http_serv = WSGIServer(("0.0.0.0", 5000), app, handler_class=WebSocketHandler)
        http_serv.serve_forever()

    - 前端:

    <!DOCTYPE html>
    <html lang="en">
    <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</title>
    <body>
    <div>
        <p>发送消息:<input type="text" id="chat">
            <button onclick="send_msg()">发送</button>
        </p>
    </div>
    <div id="msg">
    
    </div>
    <script>
        var ws = new WebSocket("ws://127.0.0.1:5000/we");
    
        ws.onmessage = function (data) {
            let p_tag = document.createElement("p");
            p_tag.innerText = data.data;
            document.getElementById("msg").appendChild(p_tag);
        };
        function send_msg() {
            var msg = document.getElementById("chat").value;
            ws.send(msg);
        }
    </script>
    </body>
    </html>

    私聊小Demo

    - 视图:

    import json
    from flask import Flask, render_template, request
    from geventwebsocket.handler import WebSocketHandler  # 开启WebSocket协议的服务
    from gevent.pywsgi import WSGIServer  # WSGI 支持多线程的 socket
    from geventwebsocket.websocket import WebSocket
    
    app = Flask(__name__)
    """
    实现单人聊天原理:
        1,获取不同用户的用户名
            1.1 利用字典的形式,用户名为key
        2,获取指定发送到某用户的用户名
        3,获取数据
    """
    
    web_socket_dict = {}
    
    
    @app.route("/we/<username>")
    def we(username):
        # print(request.environ)  # 打印原始的 request
        # print(request.environ.get("wsgi.websocket"))  # 获取ws对象
        ws = request.environ.get("wsgi.websocket")  # type: WebSocket
        web_socket_dict[username] = ws
        print(web_socket_dict)
        while 1:
            try:
                data_dict = ws.receive()  # 等待接受消息
                data = json.loads(data_dict)
                to_user = data.get("to_user")
                chat = data.get("chat")
                print(to_user, chat)
                to_from_ws = web_socket_dict.get(to_user)
                msg_data = {"from_user": username, "msg": chat}
                to_from_ws.send(json.dumps(msg_data))
            except:
                pass
            # ws.send("哼!")  # 接受到消息后,向前端发送消息
    
    
    @app.route("/chat")
    def chat():
        return render_template("chat.html")
    
    
    if __name__ == '__main__':
        http_serv = WSGIServer(("0.0.0.0", 5000), app, handler_class=WebSocketHandler)
        http_serv.serve_forever()

    - 前端:

    <!DOCTYPE html>
    <html lang="en">
    <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</title>
    <body>
    <div>
        <p>请注册您的用户名:<input type="text" id="username"></p>
        <p>注册到服务器
            <button onclick="send_username()">提交</button>
        </p>
        <p>请输入您要发送给谁:<input type="text" id="to_user"></p>
        <p>请输入您想发送的内容:<input type="text" id="chat"></p>
        <p>
            <button onclick="send_chat()">提交</button>
        </p>
    </div>
    <div id="msg"></div>
    <script>
        var ws = null;
    
        function send_username() {
            let username = document.getElementById("username").value;
            ws = new WebSocket("ws://127.0.0.1:5000/we/" + username);
            ws.onmessage = function (data) {
                console.log(data.data);
                let msg_data = JSON.parse(data.data);
                let ptag = document.createElement("p");
                ptag.innerText = msg_data.from_user + " : " + msg_data.msg;
                document.getElementById("msg").appendChild(ptag);
            }
        }
    
        function send_chat() {
            let to_user = document.getElementById("to_user").value;
            let chat = document.getElementById("chat").value;
            let data = {to_user: to_user, chat: chat};
            ws.send(JSON.stringify(data));
        }
    </script>
    </body>
    </html>
  • 相关阅读:
    java面试-Java内存模型(JMM)
    github常用操作
    java面试-生产环境服务器变慢,谈谈你的诊断思路
    java面试-JVM调优和参数配置,如何查看JVM系统参数默认值
    java面试-死锁产生、定位分析和修复
    Scalable IO in Java【java高效IO】
    java面试-JDK自带的JVM 监控和性能分析工具用过哪些?
    Docker简介
    使用docker部署项目
    公司系统遇到的问题,虽然解决了,但是,不知道原因。贴下图片,供下次参考
  • 原文地址:https://www.cnblogs.com/Fushengliangnian/p/10008966.html
Copyright © 2011-2022 走看看