zoukankan      html  css  js  c++  java
  • Django基于websocket实现群聊功能

    Django基于websocket实现群聊功能

    Django支持http协议和websocket协议,并且可以识别不同协议请求的原因是channels的ProtocolTypeRouter类的下面代码:

    #支持http协议和websocket的源代码
    class ProtocolTypeRouter:
        """
        Takes a mapping of protocol type names to other Application instances,
        and dispatches to the right one based on protocol name (or raises an error)
        """
        def __init__(self, application_mapping):
            self.application_mapping = application_mapping
            if "http" not in self.application_mapping:
                self.application_mapping["http"] = AsgiHandler
    

    关于django支持websocket的配置见上一篇文章。

    简易聊天室实现思路

    """
    http协议
    	index					>>>			index函数
    	访问:浏览器地址栏输入地址直接访问聊天页面
    	
    websocket协议
    	url配置为url(r'^chat/$',consumers.ChatConsumer)使用ChatConsumer类的方法对前端发送过来的数据进行处理,并群发
    	访问:利用js内置对象new WebSocket('ws://127.0.0.1:8080/chat/')
    """
    

    ChatConsumer的方法介绍

    websocket_connect请求websocket连接的时候自动触发
    websocket_receive前端浏览器发送消息时自动触发
    websocket_disconnect断开websocket连接时自动触发
    
    class ChatConsumer(WebsocketConsumer):
        def websocket_connect(self, message):
            """请求websocket链接的时候自动触发"""
            # print('请求链接')
            self.accept()  # 与客户端建立链接
        def websocket_receive(self, message):
            """前端浏览器发送消息自动触发"""
            print(message)  # 消息字典  {'type': 'websocket.receive', 'text': 'hahahaha'}
            # 给客户端发消息
            msg = message.get('text')
            for obj in consumer_obj_list:
                obj.send(text_data=msg)
    
        def websocket_disconnect(self, message):
            """断开websocket链接自动触发"""
            # print('断开链接')
            raise StopConsumer
    

    前端websocket对象法介绍

    onopen握手环节成功之后自动触发
    send发送数据到服务端
    onmessage服务端发送数据时触发
    onclose浏览器断开连接时执行
    close关闭websocket对象与服务端的连接
    
    <script>
        // 生产内置对象
        var ws = new WebSocket('ws://127.0.0.1:8000/chat/');
    
        // 1 握手环节成功之后自动触发  onopen
        ws.onopen = function () {
            console.log('链接成功')
        };
        // 2 发送数据       send
        function sendMsg() {
            ws.send($('#d1').val())
        }
    
        // 3 服务端发送数据自动触发   onmessage
        ws.onmessage = function (args) {
            // alert(args)  // args不是真正的数据对象 真正的数据在该对象的data属性中
            alert(args.data)
        };
        // 4 浏览器断开链接        close
        ws.onclose = function () {
            ws.close()
        }
    </script>
    

    StopConsumer

    当连接到consumer的链接关闭时,服务器会收到一个相应的event(比如,http.disconnect或websocket.disconnect),应用接受后需要作相应的处理。处理完成后,应当触发channels.exceptions.StopConsumer以彻底中止ASGI应用。如果不出发并任由应用运行,则服务器会在达到应用关闭时限后(Daphne默认10秒),结束应用并触发警告。
    通用型consumer会主动完成以上操作,只有基于AsyncConsumerSyncConsumer自定义consumer时需要注意这些。

    关于channels的consumer的详细介绍参考链接:

    https://blog.csdn.net/JosephThatwho/article/details/102614787

    实现群聊功能代码

    在app里新建consumer.py并进行如下配置

    from channels.generic.websocket import WebsocketConsumer
    from channels.exceptions import StopConsumer
    
    consumer_obj_list = []
    
    class ChatConsumer(WebsocketConsumer):
        def websocket_connect(self, message):
            """请求websocket链接的时候自动触发"""
            # print('请求链接')
            self.accept()  # 与客户端建立链接
            consumer_obj_list.append(self)
        def websocket_receive(self, message):
            """前端浏览器发送消息自动触发"""
            print(message)  # 消息字典  {'type': 'websocket.receive', 'text': 'hahahaha'}
            # 给客户端发消息
            msg = message.get('text')
            for obj in consumer_obj_list:
                obj.send(text_data=msg)
    
        def websocket_disconnect(self, message):
            """断开websocket链接自动触发"""
            # print('断开链接')
            raise StopConsumer
            
    

    routing.py

    from channels.routing import ProtocolTypeRouter,URLRouter
    from django.conf.urls import url
    from app01 import consumers
    
    application = ProtocolTypeRouter({
        'websocket':URLRouter([
            # websocket相关的url与视图函数对应关系
            url(r'^chat/$',consumers.ChatConsumer)
        ])
    })
    
    <body>
    <h1>聊天室</h1>
    <div>
        <input type="text" id="d1">
        <button onclick="sendMsg()">发送</button>
    </div>
    <h1>聊天纪录</h1>
    <div id="record"></div>
    
    <script>
        // 生产内置对象
        var ws = new WebSocket('ws://127.0.0.1:8080/chat/');
    
        // 1 握手环节成功之后自动触发  onopen
        ws.onopen = function () {
            console.log('链接成功')
        };
        // 2 发送数据       send
        function sendMsg() {
            ws.send($('#d1').val())
        }
    
        // 3 服务端发送数据自动触发   onmessage
        ws.onmessage = function (args) {
            // alert(args)  // args不是真正的数据对象 真正的数据在该对象的data属性中
            {#alert(args.data)#}
            // 将聊天纪录渲染到页面上
            pEle = $('<p>');
            pEle.text(args.data);
            $('#record').append(pEle)
        };
        // 4 浏览器断开链接        close
        ws.onclose = function () {
            ws.close()
        }
    </script>
    </body>
    
  • 相关阅读:
    Ext.grid.column.Column主要配置项及示例
    Ext.grid.Panel主要配置及示例
    EF Code First关系规则及配置
    ExtJS4系列目录
    EF Code First数据库连接配置
    ASP.NET MVC系列:ASP.NET MVC简介
    Ext JS下载及配置
    Ext.container.Viewport
    Ext.tab.Panel页签
    ASP.NET MVC系列:Controller/Action
  • 原文地址:https://www.cnblogs.com/ghylpb/p/12512823.html
Copyright © 2011-2022 走看看