Django + vue se da cuenta de la comunicación websocket

1. ¿Por qué necesitamos websocket? : El
modo de interacción más común entre el front-end y el back-end es que el front-end envía solicitudes de datos y muestra los datos en la página después de obtener los datos del back-end. Si el front-end no funciona, el back-end no puede enviar datos de forma activa al front-end, lo que también es un defecto del protocolo http.

Por lo tanto, surgió un nuevo protocolo de comunicación, websocket, cuya característica más importante es que el servidor puede enviar mensajes de forma activa al cliente y el cliente también puede enviar mensajes de forma activa al servidor, logrando una verdadera igualdad.
  Inserte la descripción de la imagen aquí
Otras características de websocket son las siguientes:

(1) Basado en el protocolo TCP, la implementación del lado del servidor es relativamente fácil.

(2) Tiene buena compatibilidad con el protocolo HTTP. Los puertos predeterminados también son 80 y 443, y el protocolo HTTP se utiliza en la fase de protocolo de enlace, por lo que no es fácil de bloquear durante el protocolo de enlace y puede pasar a través de varios servidores proxy HTTP.

(3) El formato de datos es relativamente ligero, la sobrecarga de rendimiento es pequeña y la comunicación es eficiente.

(4) Puede enviar texto o datos binarios.

(5) No hay restricción de homología y el cliente puede comunicarse con cualquier servidor.

(6) El identificador del protocolo es ws (si está cifrado, es wss) y el sitio web del servidor es la URL.

2. Parte de
Vue (lado del cliente): api.js:

export const getWebSocket = () => {
    
    
  let protocol = document.location.protocol === 'https:' ? 'wss://' : 'ws://'
  let url = protocol + document.location.host + '/nms/ws/'
  let ws = new WebSocket(url)
  ws.onopen = onOpen
  ws.onclose = onClose
  return ws
}

home.vue

...
...
...
  mounted: function() {
    
    
    this.initWebSocket()
  },
  ...
  ...
  ...
  

```javascript
  methods: {
    
    
    // ws消息处理
    initWebSocket: function () {
    
    
      this.ws = api.getWebSocket();
      this.ws.onopen = onOpen
      this.ws.onmessage  = this.onMessage;
      this.ws.onerror = this.websocketonerror;
      this.ws.onclose = this.websocketclose;
    },
    websocketonerror(){
    
    //连接建立失败重连
      this.initWebSocket();
    },
    onMessage(evt) {
    
    
      console.log(evt.data);
      let data = JSON.parse(evt.data);
      let status = "";
      // 根据需求做相应的处理
      try {
    
    
        switch (data.eventid) {
    
    
          case "aaa":
            // 抓包开始成功
            ...
            ...
            ...
            break;
          case "bbb":
            // 抓包开始失败
            ...
            ...
            ...
            break;
          ...
          ...
          ...  
          default:
            break;
        }
      } catch (err) {
    
    
        console.warn(err);
      }
    },
    websocketclose(e){
    
      //关闭
      console.log('断开连接',e);
    }
  },

3. Parte de Django (lado del servidor):
Django realiza la comunicación websocket a través de dwebsocket:
view.py

from django.shortcuts import render
import logging
import json
import threading
from dwebsocket.decorators import accept_websocket
import os
from nms_server.utils.myglobal import *
from nms_server.dao.diagnosis import add_capture_file, updata_capture_file
from nms_server.dao.redis.device import get_device_user_moid
from nms_server.rmq import RMQConsumerThread
from django.conf import settings

logger = logging.getLogger('nms.'+__name__)

# 存储连接websocket的用户

# 消费者创建标识
consumer_flag = True


@accept_websocket
def websocket_link(request):
    global consumer_flag
    # '连接websocket'
    # 获取连接
    if request.is_websocket:
        lock = threading.RLock()#rlock线程锁
        try:
            lock.acquire()#抢占资源
            s = {
    
    }
            if consumer_flag:
                try:
                    logger.info('init nms_webserver_consumer: %s' %
                                os.getpid())
                    RMQConsumerThread(
                        name='nms_webserver_consumer_{}'.format(os.getpid()),
                        amqp_url=settings.AMQP_URL,
                        exchange='nms.webserver.ex',
                        queue='nms.webserver.q.{}'.format(os.getpid()),
                        routing_key='nms.webserver.k',
                        exchange_type='topic'
                    ).start()
                    consumer_flag = False
                except Exception as e:
                    logger.error(e)
            user = getattr(request, 'sso_user', None)
            user_moid = ''
            if user is not None: 
                user_moid = user['data']['moid']
            else:
                logger.error('sso_user in None')
                raise ValueError
            
            clients = get_clients()
            #  因为同一个账号打开多个页面连接信息是不同的
            if clients.get(user_moid) != None:
                # 连接信息  键 连接名  值:连接保存
                s[str(request.websocket)] = request.websocket
                # 已存在的连接信息继续增加
                clients[user_moid].update(s)
            else:
                #  连接信息  键 连接名  值:连接保存
                s[str(request.websocket)] = request.websocket
                # 新增 用户  连接信息
                clients[user_moid] = s

            set_clients(clients)
            logger.info('pid:%d ,client: %s',os.getpid(),clients)
            # 监听接收客户端发送的消息 或者 客户端断开连接
            for message in request.websocket:
                if not message:
                    break
                else:
                    client_msg_handler(user_moid,message)
        finally:
                logger.info('close client connect,user_moid:%s,request.websocket:%s',user_moid,str(request.websocket))
                # 通过用户名找到 连接信息 再通过 连接信息 k 找到 v (k就是连接信息)
                clients = get_clients()
                clients.get(user_moid).pop(str(request.websocket))
                if not clients.get(user_moid):
                    clients.pop(user_moid)
                set_clients(clients)
                logger.info('client: %s',clients)
                #释放锁
                lock.release()

# 客户端消息处理
def client_msg_handler(user_moid,msg):
    logger.info('[client_msg_handler] msg:%s' ,msg.decode('utf-8'))

    # test代码
    # import time
    # data = {
    
    
    #     'event':'ack',
    #     'text':'hello world'
    # }
    # for i in range(5):
    #     data['id'] = i
    #     send_msg_to_client(user_moid,data)
    #     time.sleep(1)
    pass

 # 发送消息
def websocketMsg(client, msg):
    # 因为一个账号会有多个页面打开 所以连接信息需要遍历
    for cli in client:
        b1 = json.dumps(msg).encode('utf-8')
        client[cli].send(b1)

'''
@description: 服务端发送消息
@user_moid {str}  用户moid
@msg {json}  消息
@return:        
'''
def send_msg_to_client(data):
    clients = get_clients()
    logger.info('pid:%d, send_msg_to_client(data): %s',os.getpid(),data)
    logger.info('pid:%d ,client: %s',os.getpid(),clients)
    try:
        if data['user_moid'] == '':
            data['user_moid'] = get_device_user_moid(data['devid'],data['devtype'])

        user_moid = data['user_moid'] 
        if clients[user_moid]:
            if data['eventid'] == 'EV_PACKETCAPTURE_STOP_ACK':
                # 保存抓包文件到数据库
                file_name = data["url"].split("/")[-1]
                create_time = data['rpttime'].replace("/", "-").split(':',1)
                create_time = create_time[0] + " " + create_time[1]
                add_capture_file(data['user_moid'],
                                    data['devid'],
                                    file_name,
                                    data.get('size',0),
                                    create_time)

            if data['eventid'] == 'EV_PACKETCAPTURE_UPLOAD_PROGRESS_NTF':
                # 更新终端抓包文件信息
                file_name = data["url"].split("/")[-1]
                if 'size' in data:
                    updata_capture_file(data['user_moid'],
                                        data['devid'],
                                        file_name,
                                        data['size'])

            websocketMsg(clients[user_moid],data)
    except BaseException as e:
        logger.error(e)

Referencia:
python websocket Django
paquete de envío de mensajes en tiempo real solicitud de websocket ----- proyecto vue combate real
Django realiza el enlace oficial de websocket a través de dwebsocket

Supongo que te gusta

Origin blog.csdn.net/qq_34663267/article/details/108404816
Recomendado
Clasificación