zoukankan      html  css  js  c++  java
  • websocket

    一、为什么需要 WebSocket?

    初次接触 WebSocket 的人,都会问同样的问题:我们已经有了 HTTP 协议,为什么还需要另一个协议?它能带来什么好处?

    答案很简单,因为 HTTP 协议有一个缺陷:通信只能由客户端发起。

    举例来说,我们想了解今天的天气,只能是客户端向服务器发出请求,服务器返回查询结果。HTTP 协议做不到服务器主动向客户端推送信息。

    WebSocket的出现,使得浏览器具备了实时双向通信的能力

    优点:支持双向通信,更灵活,更高效,可扩展性更好。

    其他特点包括:

    (1)建立在 TCP 协议之上,服务器端的实现比较容易。

    (2)与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。

    (3)数据格式比较轻量,性能开销小,通信高效。

    (4)可以发送文本,也可以发送二进制数据。

    (5)没有同源限制,客户端可以与任意服务器通信。

    (6)协议标识符是ws(如果加密,则为wss),服务器网址就是 URL。

    WebSocket 属性

    以下是 WebSocket 对象的属性。假定我们使用了以上代码创建了 Socket 对象:

    属性描述
    Socket.readyState 只读属性 readyState 表示连接状态,可以是以下值:0 - 表示连接尚未建立。1 - 表示连接已建立,可以进行通信。2 - 表示连接正在进行关闭。3 - 表示连接已经关闭或者连接不能打开。
    Socket.bufferedAmount 只读属性 bufferedAmount 已被 send() 放入正在队列中等待传输,但是还没有发出的 UTF-8 文本字节数。

    WebSocket 事件

    以下是 WebSocket 对象的相关事件。假定我们使用了以上代码创建了 Socket 对象:

    事件事件处理程序描述
    open Socket.onopen 连接建立时触发
    message Socket.onmessage 客户端接收服务端数据时触发
    error Socket.onerror 通信发生错误时触发
    close Socket.onclose 连接关闭时触发

    WebSocket 方法

    以下是 WebSocket 对象的相关方法。假定我们使用了以上代码创建了 Socket 对象:

    方法描述
    Socket.send() 使用连接发送数据
    Socket.close() 关闭连接

    示例

    // 初始化一个 WebSocket 对象
    var ws = new WebSocket("ws://localhost:9998/echo");
    
    // 建立 web socket 连接成功触发事件
    ws.onopen = function () {
      // 使用 send() 方法发送数据
      ws.send("发送数据");
      alert("数据发送中...");
    };
    
    // 接收服务端数据时触发事件
    ws.onmessage = function (evt) {
      var received_msg = evt.data;
      alert("数据已接收...");
    };
    
    // 断开 web socket 连接成功触发事件
    ws.onclose = function () {
      alert("连接已关闭...");
    };

    后端代码:

    from flask import Flask,request,render_template
    from geventwebsocket.handler import  WebSocketHandler  #
    from gevent.pywsgi import  WSGIServer  #  启动服务 为了让的服务支持Wsgi
    from geventwebsocket.websocket import WebSocket  # 实现你的websocket的模块
    import json
    app = Flask(__name__)
    
    user_dict = {}
    
    @app.route("/<username>")
    def index(username):
        print(333)
        user_socket = request.environ.get("wsgi.websocket")  #把用户的信息存在了eviron字典中 然后键是wsgi.websocket  这样取到的是用户的信息
        print(user_socket)
        if user_socket:
            user_dict[username] = user_socket  #把用户的信息存进字典
            print(user_dict)
        while True:
            msg = user_socket.receive() #收到消息
            recv_msg = json.loads(msg)  #把你发来的消息反序列化
    
            send_msg = {
                "user_name":recv_msg.get("user_name"),  #取到username
                "msg":recv_msg.get("msg")  #取到用户信息
            }
            print(send_msg)
            for i in user_dict.values():  #循环你的消息字典 如果你的对象等于本机的  就直接返回 不去管
                if i == user_socket:
                    continue
                i.send(json.dumps(send_msg))
    
    
    @app.route("/ws")
    def ws():
        print(333)
        return render_template("群聊.html")
    
    if __name__ == "__main__":
        http_serv = WSGIServer(("0.0.0.0",9980),app,handler_class=WebSocketHandler)
        http_serv.serve_forever()

    前端界面:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>群聊</title>
    </head>
    <body>
    你的昵称: <input type="text" id="nickname">
    
    <button onclick="connws()">连接服务器</button>
    
    <br><br>
    发送消息: <input type="text" id="talk">
    <button onclick="send_msg()">发送消息</button>
    
    <div style=" 500px;height: 200px;border: 1px red solid;" id="text">
    
    </div>
    </body>
    
    <script type="application/javascript">
    
        var user_name = null;
        var ws = null;
        function connws(){//这个是你的信息进行提交的时候
            user_name = document.getElementById("nickname").value;
            ws = new WebSocket("ws://192.168.11.63:9980/"+user_name);
    
            ws.onmessage = function(data){  // onmessage接收消息
                var recv_msg = JSON.parse(data.data);
                {#console.log(recv_msg);#}
                createDiv(recv_msg.user_name,recv_msg.msg) //把你发送的信息渲染到那个框中
            }
        }
    
        function send_msg(){ //这个你要发送的信息或者他人要发送的信息
            var talk = document.getElementById("talk").value;  //  获取你的提交的信息
            createDiv("w",talk);
            send_str = {
                user_name:user_name,
                msg:talk
            };
            ws.send(JSON.stringify(send_str));
        };
    
        function createDiv(self,content){  // 这个是提交信息的时候下面出现的对话框
            var divtag = document.createElement("div");  //定义个div标签
            var who = self+" : ";
            if (self == "w"){
                who = "我 : ";
            }
            divtag.innerText = who + content;  //如果事其他人的话就把你的信息给 他人的名字加上信息
               var text = document.getElementById("text");
               text.appendChild(divtag)
        }
    </script>
    </html>
  • 相关阅读:
    mybatis
    Spring原理
    JS 之继承
    HTTP协议简介2
    JS 之原型,实例,构造函数之间的关系
    HTTP协议简介1
    freemarker语法简介
    CSS 动画之十-图片+图片信息展示
    JS实现颜色值的转换
    抓包工具charles的使用
  • 原文地址:https://www.cnblogs.com/zhaoyunlong/p/9607255.html
Copyright © 2011-2022 走看看