06.websocket

websocket:https://www.cnblogs.com/xiaonq/p/12238651.html

webssh:https://www.cnblogs.com/xiaonq/p/12243024.html

什么是websocket

1、webSocket是一种在单个TCP连接上进行全双工通信的协议
2、客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。
3、浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输

websocket与http区别

1、http请求建立连接只能发送一次请求,不能有服务器端主动向客户端发送请求
2、websocket建立的长连接,一次连接,后续一直通信,这样节省资源,可以有客户端发送请求给服务器端

远古时期解决方案就是轮询

1、客户端以设定的时间间隔周期性地向服务端发送请求,频繁地查询是否有新的数据改动(浪费流量和资源)

webSocket应用场景?

1、**聊天软件:**最著名的就是微信,QQ,这一类社交聊天的app
2、**弹幕:**各种直播的弹幕窗口
3、**在线教育:**可以视频聊天、即时聊天以及其与别人合作一起在网上讨论问题…

websocket原理

1、websocket首先借助http协议(通过在http头部设置属性,请求和服务器进行协议升级,升级协议为websocket的应用层协议)
2、建立好和服务器之间的数据流,数据流之间底层还是依靠TCP协议;
3、websocket会接着使用这条建立好的数据流和服务器之间保持通信;
4、由于复杂的网络环境,数据流可能会断开,在实际使用过程中,我们在onFailure或者onClosing回调方法中,实现重连

websocket实现心跳检测的思路

1、通过setInterval定时任务每个3秒钟调用一次reconnect函数
2、reconnect会通过socket.readyState来判断这个websocket连接是否正常
3、如果不正常就会触发定时连接,每4s钟重试一次,直到连接成功
4、如果是网络断开的情况下,在指定的时间内服务器端并没有返回心跳响应消息,因此服务器端断开了。
5、服务断开我们使用ws.close关闭连接,在一段时间后,可以通过 onclose事件监听到。

实现聊天功能

# 后端的django代码
from django.shortcuts import render
from dwebsocket.decorators import accept_websocket,require_websocket
from django.http import HttpResponse


def index(request):
    return render(request, 'index.html')

from dwebsocket.backends.default.websocket import DefaultWebSocket  # request.websocket就是DefaultWebSocket对象

tmp = []
# 只有加了这个装饰器,这个视图函数才能处理websocket请求
@accept_websocket
def echo(request):
    if not request.is_websocket():  #判断是不是websocket连接
        try:  #如果是普通的http方法
            message = request.GET['message']
            return HttpResponse(message)
        except:
            return render(request,'index.html')
    else:
        '''1.实现消息推送'''
        tmp.append(request.websocket)  # 把所有连接的websocket连接都加入列表中
        #  request.websocket = <dwebsocket.backends.default.websocket.DefaultWebSocket object at 0x00000272E69A4320>
        # failed:Invalid frame header:你的视图没有阻塞,请求过一次后服务器端就关闭连接了
        # 所以使用for循环 request.websocket 对象就会调用 __iter__()方法,利用迭代器进行阻塞
        for message in request.websocket:
            for ws in tmp:
                ws.send(message)

        '''2.实现聊天室思路'''
        # d = {}                                # 使用了一个dict来保存数据,
        # d['zhangsan'] = request.websocket     # key值是用户身份,value值是dict类型的{username:websocket}。
        # d['zhangsan'].send(message)           # 发送消息到客户端
        # d['lisi'].send(message)   ==>  request.websocket.send(message)

        # 这只是个思路,如果正式使用的话,肯定会对group封装,也不会只保存在内存中,需要保存到redis中去
        # 并且对每个websocket对象设置有效期,过期清除,避免长期挂起状态消耗系统资源等
# 前端VUE代码
<template>
  <div>
    <button @click="send">发消息</button>
  </div>
</template>

<script>
  export default {
    data () {
      return {
        path:"ws://127.0.0.1:8000/echo?username=zhangsan&token=xxxx",
        socket:""
      }
    },
    mounted () {
      // 初始化
      this.init()
    },
    methods: {
      init: function () {
        if(typeof(WebSocket) === "undefined"){
          alert("您的浏览器不支持socket")
        }else{
          // 实例化socket
          this.socket = new WebSocket(this.path)
          // 监听socket连接
          this.socket.onopen = this.open
          // 监听socket错误信息
          this.socket.onerror = this.error
          // 监听socket消息
          this.socket.onmessage = this.getMessage
        }
      },
      open: function () {
        console.log("socket连接成功")
      },
      error: function () {
        console.log("连接错误")
      },
      getMessage: function (msg) {
        console.log(msg.data)         // 打印后台返回的数据
      },
      send: function () {
        var params = 'hahahahhahaha';
        this.socket.send(params)      // 发送给后台的数据
      },
      close: function () {
        console.log("socket已经关闭")
      }
    },
    destroyed () {
      // 销毁监听
      this.socket.onclose = this.close
    }
  }
</script>

<style>

</style>

 

posted @ 2021-03-26 11:35  小虾米爱吃鱼  阅读(91)  评论(0编辑  收藏  举报