【websocket】django channls 实现核心文件,配合redis实时主推更新数据

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from channels.generic.websocket import WebsocketConsumer
from channels.generic.websocket import AsyncWebsocketConsumer
from channels.exceptions import StopConsumer
from asgiref.sync import async_to_sync

# 导入redis配置
import redis
from api.redis_cli import Pool

# 用户列表
USERLIST = {}

class ChatConsumer(WebsocketConsumer):

    # 服务端接收连接,像客户端发送一个加密字符串
    def websocket_connect(self, message):

        # 固定获取参数格式   self.scope 所有前端来的请求参数
        username  = self.scope[url_route][kwargs].get("username")
        room_id  = self.scope[url_route][kwargs].get("room_id")

        # self.channel_name 生成随机字符串ID 代表的是连接的自己
        async_to_sync(self.channel_layer.group_add)(room_id, self.channel_name)

        # 连接
        self.accept()

        sr = redis.Redis(connection_pool=Pool)
        res = sr.hget(room_id,"room")
        # print("res",res)

        if res == None:
            # 如果没有有用户在这个房间
            sr.hset(room_id,"room",username)
            user_list = username
        else:
            if username in res.split("-"):
                user_list = res
            else:
                # 如果房间已经存在用户 那么就增加用户组
                user_list = res + "-" + username

            # print("增加之后的",user_list)
            sr.hset(room_id,"room",user_list)


        # 发消息  这里面是可以定义自己发送的内容
        async_to_sync(self.channel_layer.group_send)(room_id, {
            type: make.first,
            message: user_list,
        })



    # 客户端向服务端发送消息,此方法被触发
    def websocket_receive(self, text_data=None, bytes_data=None,):
        """
            :param text_data[‘text‘]: 接收到的消息
        """

        username = self.scope[url_route][kwargs].get("username")
        room_id = self.scope[url_route][kwargs].get("room_id")


        # 针对群体发消息
        async_to_sync(self.channel_layer.group_send)(room_id, {
            type: make.send,
            message: "2#" + username + "#" +  text_data[text]
        })



    # 断开连接
    def websocket_disconnect(self, message):

        print(客户端断开连接了)

        username = self.scope[url_route][kwargs].get("username")

        room_id = self.scope[url_route][kwargs].get("room_id")

        # 踢出群
        async_to_sync(self.channel_layer.group_discard)(room_id, self.channel_name)

        # 先取出redis里面的这个房间的用户
        sr = redis.Redis(connection_pool=Pool)
        res = sr.hget(room_id,"room")
        res_list = res.split("-")

        # 获取改房间用户组,移除退出的用户
        try:
            res_list.remove(username)
        except:
            pass

        # 整理剩下的用户 填入redis
        if len(res_list) == 0:
            sr.expire(room_id, 1)
        user_list = ""
        if len(res_list) == 1:
            user_list = res_list[0]
        else:
            for user in res_list:
                user_list = user + "-" + user_list
            user_list = user_list[0:-1]

        # 传入redis
        sr = redis.Redis(connection_pool=Pool)
        sr.hset(room_id,"room", user_list)

        # 发消息  这里面是可以定义自己发送的内容
        async_to_sync(self.channel_layer.group_send)(room_id, {
            type: make.first,
            message: user_list,
        })

        raise StopConsumer()


    # 发消息内容
    def make_first(self, event):

        # event储存着上面定义的内容
        message = "1#" + event[message]
        self.send(message)

    # 回复群里的消息    event相当于是text_data
    def make_send(self, event):

        message = event[message]
        self.send(message)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Talking</title>
    <link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/4.3.1/css/bootstrap.min.css">
    <script src="https://cdn.staticfile.org/jquery/3.2.1/jquery.min.js"></script>
    <script src="https://cdn.staticfile.org/popper.js/1.15.0/umd/popper.min.js"></script>
    <script src="https://cdn.staticfile.org/twitter-bootstrap/4.3.1/js/bootstrap.min.js"></script>
    <style>
        #taking {
            width: 100%;
            height: 700px;
            background: #42fbff;
        }

        img{
            max-height: 200px;
            max-width: 200px;
        }
    </style>
</head>
<body>
<div id="app" class="container">
    <div class="card-header">在线聊天室</div>

    <span style="color: red;font-size: 18px">当前在线用户: {%verbatim %} {{ userList }} {% endverbatim %}</span>
    <div id="taking">

        <ul>
            <li v-for="item in chat">{%verbatim %} {{ item }} {% endverbatim %}</li>
            {#            <li v-for="item in chat"><img src=""> </li>#}
        </ul>

    </div>
    <div style="width: 100%;height: 80px">
        <textarea type="text" v-model="txt" placeholder="请输入内容" style="width: 100%;height: 100%"></textarea>
    </div>

    <button class="btn btn-primary" style="width: 100px" @click="send">发送</button>
    <button class="btn btn-primary" style="width: 100px" @click="sendimages">发送图片</button>
    <input type="file" name="file" id="file"/>
    <button class="btn btn-danger" style="width: 100px" @click="close">断开连接</button>
</div>
</body>
</html>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
    var vmm = new Vue({
        el: #app,
        data: {

            txt: "",
            path: "ws://127.0.0.1:8001/chat/",
            socket: "",
            base:"",
            chat: [],
            userList: ""

        },

        mounted() {
            // 初始化
            this.init()
        },


        methods: {
            close() {
                this.chat.push("socket已断开")
                this.socket.close()
            },


            destroyed() {
                // 销毁监听
                this.socket.onclose = this.close
            },


            // 初始化
            init: function () {

                function random(min, max) {
                    return Math.floor(Math.random() * (max - min)) + min;
                }

                if (typeof (WebSocket) === "undefined") {
                    alert("您的浏览器不支持socket")
                } else {
                    // 实例化socket
                    this.socket = new WebSocket(this.path + sessionStorage.getItem(token) + "/")

                    // 监听socket连接
                    this.socket.onopen = this.open
                    // 监听socket错误信息
                    this.socket.onerror = this.error
                    // 监听socket消息
                    this.socket.onmessage = this.getMessage
                }
            },

            open() {
                this.chat.push("socket连接成功")
            },

            error() {
                alert("连接错误")
            },


            // 渲染消息
            getMessage(msg) {
                // 在线人数
                if (msg.data.split("#")[0] === "1") {
                    this.userList = msg.data.split("#")[1]
                } else {
                    // 在线内容
                    if (msg.data.split("#")[2].length > 500){
                        var user = msg.data.split("#")[1] + ":"
                        var src = msg.data.split("#")[2]
                        var $ele = ("<li>" + user + " <img src=" + src +"></li>")

                        $("ul").append($ele)

                    }else {
                        this.chat.push(msg.data.split("#")[1] + ":" + msg.data.split("#")[2])
                    }

                }
            },

            // 发送消息
            send() {
                this.socket.send(this.txt)
            },


            //传入图片路径,返回base64
            getBase64(img) {
                function getBase64Image(img, width, height) {//width、height调用时传入具体像素值,控制大小 ,不传则默认图像大小
                    var canvas = document.createElement("canvas");
                    canvas.width = width ? width : img.width;
                    canvas.height = height ? height : img.height;
                    var ctx = canvas.getContext("2d");
                    ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
                    var dataURL = canvas.toDataURL();
                    return dataURL;
                }
                var image = new Image();
                image.crossOrigin = ‘‘;
                image.src = img;
                var deferred = $.Deferred();
                if (img) {
                    image.onload = function () {
                        deferred.resolve(getBase64Image(image));//将base64传给done上传处理
                    }
                    return deferred.promise();
                }
            },


            // 获取文件对象 转换成它的url暂缓地址
            getObjectURL(file) {
                var url = null;
                if (window.createObjcectURL != undefined) {
                    url = window.createOjcectURL(file);
                } else if (window.URL != undefined) {
                    url = window.URL.createObjectURL(file);
                } else if (window.webkitURL != undefined) {
                    url = window.webkitURL.createObjectURL(file);
                }
                return url;
            },

            // 转换编码  发送图片
            sendimages() {
                that = this
                var inputElement = document.getElementById("file")
                var file = inputElement.files

                var objURL = this.getObjectURL(file[0]);

                // 获取64
                this.getBase64(objURL)
                    .then(function (base64) {
                        {#console.log(typeof(base64));//处理成功打印在控制台#}
                        that.base = base64
                        that.socket.send(that.base)

                    }, function (err) {
                        console.log(err);//打印异常信息
                    });


            }
        },


    })
</script>

 

【websocket】django channls 实现核心文件,配合redis实时主推更新数据

上一篇:php安装event扩展


下一篇:HTML-<17-29>