• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

理解WebSocket

武飞扬头像
叱咤少帅(少帅)
帮助1

背景

比如我们想要实现webssh或者web界面能实时查到日志,这个时候websocket就很有用了

为什么需要 WebSocket?

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

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

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

这种单向请求的特点,注定了如果服务器有连续的状态变化,客户端要获知就非常麻烦。我们只能使用"轮询":每隔一段时候,就发出一个询问,了解服务器有没有新的信息。最典型的场景就是聊天室。

轮询的效率低,非常浪费资源(因为必须不停连接,或者 HTTP 连接始终打开)。因此,工程师们一直在思考,有没有更好的方法。WebSocket 就是这样发明的。

参考文档

文档参考: https://www.ruanyifeng.com/blog/2017/05/websocket.html

简介

WebSocket 协议在2008年诞生,2011年成为国际标准。所有浏览器都已经支持了。

它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。

学新通

 其他特点包括:

  • 建立在 TCP 协议之上,服务器端的实现比较容易。
  • 与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。
  • 数据格式比较轻量,性能开销小,通信高效。
  • 可以发送文本,也可以发送二进制数据。
  • 没有同源限制,客户端可以与任意服务器通信。
  • 协议标识符是ws(如果加密,则为wss),服务器网址就是 URL。
ws://example.com:80/some/path

学新通

WebSocket 属性

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

属性 描述
Socket.readyState

只读属性 readyState 表示连接状态,可以是以下值:

  • 0 - 表示连接尚未建立。

  • 1 - 表示连接已建立,可以进行通信。

  • 2 - 表示连接正在进行关闭。

  • 3 - 表示连接已经关闭或者连接不能打开。

Socket.bufferedAmount

只读属性 bufferedAmount 已被 send() 放入正在队列中等待传输,但是还没有发出的 UTF-8 文本字节数。

前端实现

客户端支持WebSocket的浏览器中,在创建socket后,可以通过onopen、onmessage、onclose和onerror四个事件对socket进行响应。

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

  1.  
    //申请一个WebSocket对象,参数是服务端地址,同http协议使用http://开头一样,WebSocket协议的url使用ws://开头,另外安全的WebSocket协议使用wss://开头
  2.  
     
  3.  
    var ws = new WebSocket("ws://localhost:8080");
  4.  
     
  5.  
     
  6.  
    ws.onopen = function(){  //当WebSocket创建成功时,触发onopen事件
  7.  
    console.log("open");  
  8.  
    ws.send("hello"); //将消息发送到服务端
  9.  
    }
  10.  
     
  11.  
    ws.onmessage = function(e){  
  12.  
    //当客户端收到服务端发来的消息时,触发onmessage事件,参数e.data包含server传递过来的数据  
  13.  
    console.log(e.data);
  14.  
    }
  15.  
     
  16.  
    ws.onclose = function(e){  
  17.  
    //当客户端收到服务端发送的关闭连接请求时,触发onclose事件 
  18.  
     console.log("close");}
  19.  
    ws.onerror = function(e){ 
  20.  
      //如果出现连接、处理、接收、发送数据失败的时候触发onerror事件
  21.  
      console.log(error);
  22.  
    }
学新通

其他案例用于理解前端:

  1.  
    <!DOCTYPE html>
  2.  
    <html>
  3.  
    <head>
  4.  
    </head>
  5.  
    <style>
  6.  
    #msg{
  7.  
    width:400px; height:400px; overflow:auto;
  8.  
    }
  9.  
    </style>
  10.  
    </head>
  11.  
    <body>
  12.  
    <p>实时日志</p>
  13.  
    <div id="msg"></div>
  14.  
    <script src="http://libs.百度.com/jquery/1.9.1/jquery.min.js"></script>
  15.  
    <script>
  16.  
    $(document).ready(function() {
  17.  
    /* !window.WebSocket、window.MozWebSocket检测浏览器对websocket的支持*/
  18.  
    if (!window.WebSocket) {
  19.  
    if (window.MozWebSocket) {
  20.  
    window.WebSocket = window.MozWebSocket;
  21.  
    } else {
  22.  
    $('#msg').prepend("<p>你的浏览器不支持websocket</p>");
  23.  
    }
  24.  
    }
  25.  
    /* ws = new WebSocket 创建WebSocket的实例 注意设置对以下的websocket的地址哦*/
  26.  
    ws = new WebSocket('ws://192.168.2.222:8000/websocket/');
  27.  
    /*
  28.  
    ws.onopen 握手完成并创建TCP/IP通道,当浏览器和WebSocketServer连接成功后,会触发onopen消息
  29.  
    ws.onmessage 接收到WebSocketServer发送过来的数据时,就会触发onmessage消息,参数evt中包含server传输过来的数据;
  30.  
    */
  31.  
    ws.onopen = function(evt) {
  32.  
    $('#msg').append('<li>websocket连接成功</li>');
  33.  
    }
  34.  
    ws.onmessage = function(evt) {
  35.  
    $('#msg').prepend('<li>' evt.data '</li>');
  36.  
    }
  37.  
    });
  38.  
    </script>
  39.  
    </body>
  40.  
    </html>
学新通

webSocket.onmessage:

实例对象的onmessage属性,用于指定收到服务器数据后的回调函数。

  1.  
    ws.onmessage = function(event) {
  2.  
    var data = event.data;
  3.  
    // 处理数据
  4.  
    };
  5.  
     
  6.  
    ws.addEventListener("message", function(event) {
  7.  
    var data = event.data;
  8.  
    // 处理数据
  9.  
    });

注意,服务器数据可能是文本,也可能是二进制数据(blob对象或Arraybuffer对象)。

  1.  
    ws.onmessage = function(event){
  2.  
    if(typeof event.data === String) {
  3.  
    console.log("Received data string");
  4.  
    }
  5.  
     
  6.  
    if(event.data instanceof ArrayBuffer){
  7.  
    var buffer = event.data;
  8.  
    console.log("Received arraybuffer");
  9.  
    }
  10.  
    }

后端的实现

官网: Django Channels — Channels 3.0.4 documentation

要实现websocket,那么前端和后端都需要进行编写,才能实现前后端。

django实现websocket大致上有两种方式,一种channels,一种是dwebsocket

注意:Django 3.0 以上不支持dwebsocket模块,启动时,会报错:

  1.  
    File "D:\py-res\project_devops\devops\ces\views.py", line 8, in <module>
  2.  
    def webst(request):
  3.  
    File "D:\Program Files\Python38\lib\site-packages\dwebsocket\decorators.py", line 31, in accept_websocket
  4.  
    func = _setup_websocket(func)
  5.  
    File "D:\Program Files\Python38\lib\site-packages\dwebsocket\decorators.py", line 24, in _setup_websocket
  6.  
    new_func = decorator(new_func)
  7.  
    File "D:\Program Files\Python38\lib\site-packages\django\utils\decorators.py", line 117, in _decorator
  8.  
    middleware = middleware_class(view_func, *m_args, **m_kwargs)
  9.  
    TypeError: WebSocketMiddleware() takes no arguments

因此,如果使用Django 3.0 或者以上,必须使用channels。

其他案例理解后端:

  1.  
    #!/usr/bin/env python
  2.  
    # -*- coding:utf-8 -*-
  3.  
    from bottle import get, run
  4.  
    from bottle.ext.websocket import GeventWebSocketServer
  5.  
    from bottle.ext.websocket import websocket
  6.  
    users = set() # 连接进来的websocket客户端集合
  7.  
    @get('/websocket/', apply=[websocket])
  8.  
    def chat(ws):
  9.  
    users.add(ws)
  10.  
    while True:
  11.  
    msg = ws.receive() # 接客户端的消息
  12.  
    if msg: # 也可以不判断,直接服务端检测内容直接推送给客户端
  13.  
    for u in users:
  14.  
    u.send(msg) # 发送信息给所有的客户端
  15.  
    else:
  16.  
    break
  17.  
    # 如果有客户端断开连接,则踢出users集合
  18.  
    users.remove(ws)
  19.  
    run(host='0.0.0.0', port=8000, server=GeventWebSocketServer)
学新通

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgekkbe
系列文章
更多 icon
同类精品
更多 icon
继续加载