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>
原文地址:https://www.cnblogs.com/zhaoyunlong/p/9607255.html