django、vue如何实现websock通信,如何实现多人群聊

       django可以通过channels或者dwebsocket去实现,但是dwebsocket不支持django3.x,所以使用channels来实现前后端的通信, 实现功能  建立群聊

一、各种前后端配置

1、django安装

安装指定版本的包

        pip install channels==3.0.4

        pip install channels_redis

2、vue安装:

使用chat_ui插件

        npm install --save @maybecode/m-chat

        同时配置到main中:

        import MChat from '@maybecode/m-chat'

        Vue.use(MChat)

3、django中注册channels

        在配置文件settings的INSTALLED_APPS中加入'channels'

4、在setting中配置asgi

这里为什么用asgi不用wsgi,因为wsgi不支持websocket通信。

WSGI_APPLICATION = 'dyz_account.wsgi.application'
ASGI_APPLICATION = 'dyz_account.asgi.application'

CHANNEL_LAYERS = {
    'default': {
        'BACKEND': 'channels_redis.core.RedisChannelLayer',
        'CONFIG': {
            # 自己的redis地址
            "hosts": [('127.0.0.1', 6379)],
        },
    },
}

二、前后端的主要代码

1、在主项目下修改或添加asgi.py文件

import os
from django.core.asgi import get_asgi_application
from channels.routing import ProtocolTypeRouter, URLRouter

from . import routing
from channels.auth import AuthMiddlewareStack
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'dyz_account.settings')


application = ProtocolTypeRouter({
    "http": get_asgi_application(),
    "websocket": AuthMiddlewareStack(URLRouter(routing.websocket_urlpatterns)),
})

2、在settings同级目录中创建routing.py。注册路由

from django.urls import path
from dyz_account.consumers import ChatConsumer

websocket_urlpatterns = [
    path('ws/chat', ChatConsumer.as_asgi()),
]

3、创建consumer.py文件,处理websocket通信逻辑

import json

from asgiref.sync import async_to_sync
from channels.generic.websocket import WebsocketConsumer
from channels.exceptions import StopConsumer

CONN_LIST = []


class ChatConsumer(WebsocketConsumer):
    def websocket_connect(self, message):
        print("开始链接...")
        # 有客户端来向后端发送websocket连接的请求时,自动触发。
        # 服务端允许和客户端创建连接(握手)。
        self.accept()

        CONN_LIST.append(self)

    def websocket_receive(self, message):
        print('22222222', message)
        data = json.loads(message.get('text', '{}'))
        chat_type = data.get('chat_type')
        chat_id = data.get('chat_id')
        chat_content = data.get('message')
        if chat_type == 'add_chat':
            async_to_sync(self.channel_layer.group_add)(chat_id, self.channel_name)
        else:
            async_to_sync(self.channel_layer.group_send)(chat_id, {"type": 'chat.message', 'message': message})

    def chat_message(self, event):
        self.send(event['message']['text'])

    def websocket_disconnect(self, message):
        CONN_LIST.remove(self)
        raise StopConsumer()

4、前端进行websocket连接,

<template>
  <div style="width: 60%; margin-left: 20%">
    <div class="message" id="message"></div>
    <div v-show="add_chat">
      <input
        type="text"
        placeholder="请输入群聊id"
        id="txt"
        v-model="chat_id"
      />
      <input type="button" value="加入群聊" @click="addChat()" />
    </div>
    <div v-show="send_chat">
      <m-chat
        ref="mChat"
        :messages="messages"
        @submit="submit"
        :loadMore="loadMore"
        height="100vh"
        :openExtends="open_extends"
      >
      </m-chat>
    </div>
    <div>

    </div>
  </div>
</template>

<script>
// import { } from "@/components/axios_api/api.js"; // @符号指的是src路径
import MChat from "@maybecode/m-chat";
export default {
  data() {
    return {
      user_id: "",
      send_data: "",
      chat_id: null,
      send_chat: false,
      add_chat: true,
      messages: [],
      open_extends: ["image"],
    };
  },
  components: {
    MChat,
  },
  methods: {
    submit(content) {
      this.sendMessage(content["content"]);
    },

    loadMore() {},
    // 加入群聊,如果有对应的id,进入群聊,没有则创建一个新的群聊
    addChat() {
      var userid = localStorage.getItem("user_id");
      if (userid) {
        if (this.chat_id) {
          this.initWebSocket();
          this.send_chat = true;
          this.add_chat = false;
        } else {
          alert("请输入群聊号");
        }
      }else{
        alert('拜拜')
        this.$router.push('/login')
      }
    },
    initWebSocket() {
      //初始化websocket 可以使用自己的ip地址
        
      var wsuri = "ws://127.0.0.1:8000";
      // var ws_scheme = window.location.protocol === "https:" ? "wss" : "ws";
      var ws_on_line = wsuri + "/ws/chat";
      // 本地走代理/vue.config.js,线上也代理nginx代理
      console.log("111111111111", ws_on_line);

      // var ws_scheme = window.location.protocol==="https:"?"wss":"ws"
      this.websock = new WebSocket(ws_on_line);
      this.websock.onopen = this.websocketonopen;
      this.websock.onmessage = this.websocketonmessage;
      this.websock.onerror = this.websocketonerror;
      // this.websock.onclose = this.websocketclose;
    },
    websocketonopen() {
      //连接建立之后执行send方法发送数据
      console.log("建立连接");
      var actions = { message: "连接测试" };
      var type = "add_chat";
      this.sendMessage(actions, type);
    },

    websocketonerror(e) {
      //连接建立失败重连
      console.log("连接error", e);
      // this.initWebSocket();
    },

    websocketonmessage(e) {
      //数据接收
      this.websocket_data = JSON.parse(e.data);
      console.log("websocket-res", JSON.stringify(this.websocket_data));
      console.log("接收后端数据type", typeof this.websocket_data);
      let message_user_id = this.websocket_data["username"];
      let message_self = false;
      // 判断当前消息是否自己发出
      if (message_user_id == localStorage.getItem("username")) {
        message_self = true;
      }else{
        message_self = false
      }
      let name = this.websocket_data.username;
      // 将websocket消息展示在消息提示框
      var count = this.messages.length;
      var push_message = {
        type: "text",
        content: { text: JSON.stringify(this.websocket_data.message) },
        id: count + 1,
        self: message_self,
        name: name,
      };
      this.messages.push(push_message);
      var h = this.$createElement;
      // 创建html元素
      this.hrender = h("p", null, [
        h(
          "div",
          [
            h("div", JSON.stringify(this.websocket_data.message)),
            // 传变量
            //   },
            // }),
          ],
          null
        ),
      ]);
    },
    sendMessage(Data, type = "send_data") {
      //数据发送
      console.log("222222222222");
      this.websock.send(
        JSON.stringify({
          chat_id: this.chat_id,
          message: Data,
          chat_type: type,
          username: localStorage.getItem("username"),
          user_id: localStorage.getItem("user_id"),
          //在登录的时候进行保存信息  
        })
      );
    },

    websocketclose(e) {
      //关闭
      console.log("断开连接", e);
    },
    userinfo() {},
  },
  mounted() {},
};
</script>

<style>
</style>

5、需要在登录时保存用户信息

<template>
    <p>账号:<input type="text" v-model="user"></p>
      <p>密码:<input type="password" v-model="pwd"></p>
      <p><button @click="login">登录</button></p>
</template>

<script>
import {post} from "../../utils/request"
export default {
    data(){
        return{
            user:"",
            pwd:""
        }
    },
    methods:{
        login(){
            post("/user/sms_phone/",{username:this.user,password:this.pwd}).then(resp=>{
                console.log(resp)
                if(resp.status==200){
                    console.log(resp.data.token)
                    localStorage.setItem("username", resp.data.username)
                    localStorage.setItem('user_id',resp.data.user_id)
                    localStorage.setItem('token',resp.data.token)
                    console.log('-------------',resp.data.username,resp.data.user_id)
                    alert("登录成功")
                }
            }).catch(err=>{
                console.log(err)
            })
        },
    }
}
</script>

<style>

</style>

6、参考相关连接地址

m-chat: 基于vue 聊天(IM) UI组件https://gitee.com/null_639_5368/m-chat#popitemclick-demo

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值