Django channels 实现websocket实时通讯

运维平台的一定少不了这样的场景,即需要实时获取后端数据,例如批量执行的结果,或者监控的状态获取,这个如果单靠浏览器频繁的请求后端接口来更新数据,多少显得有点low

所以对django如何支持websocket长连接进行简单的学习,以便后面集成到项目中

安装channels:

pip3 install channels

先将channels注册到app中:

INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'channels',
'app',
'websocket',
'django_celery_beat',
'django_celery_results',
]

在配置文件中指定ASIG路由地址,因为django默认是wsgi协议,channels就是通过asig,异步网关协议实现了websocket

ASGI_APPLICATION = 'captain.routing.application'

然后启动django:

image.png

创建一个独立的app:

python manage.py startapp websocket

在项目目录下创建asgi.py文件:

"""
ASGI entrypoint. Configures Django and then runs the application
defined in the ASGI_APPLICATION setting.
"""
import os
import django
from channels.routing import get_default_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'captain.settings')
django.setup()
application = get_default_application()

在项目目录下创建路由文件:

from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
import websocket.routing
application = ProtocolTypeRouter({
'websocket': AuthMiddlewareStack(
URLRouter(
websocket.routing.websocket_urlpatterns
)
),
})


在app下面创建路由文件,将path和处理webscoket请求的函数进行绑定:

from django.urls import path
from websocket.consumers import ChatConsumer
websocket_urlpatterns = [
path('ws/chat/', ChatConsumer),
]


在app下面创建视图,处理请求函数:

from channels.generic.websocket import WebsocketConsumer
from channels.exceptions import StopConsumer
class ChatConsumer(WebsocketConsumer):
def websocket_connect(self, message):
"""
        客户端发送请求进来,触发此方法
        :param message:
        :return:
        """
self.accept()
def websocket_receive(self, message):
"""
        客户端发送消息,触发此方法,并返回数据
        :param message:
        :return:
        """
print(message)
msg = message['text']
self.send(msg)
def websocket_disconnect(self, message):
"""
        客户端主动断开链接,触发此方法
        :param message:
        :return:
        """
# 服务端触发异常 StopConsumer
raise StopConsumer

创建前端测试文件:

➜  ~ cat socket.html
<div>
    <div>
        <input type="text" id="txt">
        <input type="button" value="send" onclick="sendMsg();">
        <input type="button" value="close" onclick="closeConn();">
    </div>
    <h2>聊天记录</h2>
    <div id="content">
    </div>
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.0/jquery.min.js"></script>
<script>
    var ws = new WebSocket("ws://127.0.0.1:8088/ws/chat/");
    ws.onopen = function(){
        // 客户端验证握手环节完成之后,自动执行该方法
        console.log("链接成功。。。")
    };
    ws.onmessage = function (event) {
        //  接受服务端发送的消息
        //  客户端完成握手验证之后 触发该方法
        console.log(event.data);
        var tag = $("<div>");
        tag.text(event.data);
        $("#content").append(tag);
        console.log(1)
    };
    function sendMsg() {
        // ws.send():发送消息
      ws.send($("#txt").val());
    };
    function closeConn() {
        // ws.close():关闭Websocket链接
        console.log("断开链接。。。");
        ws.close();
    };
</script>


一个简单的聊天室就创建好了

image.png

猜你喜欢

转载自blog.51cto.com/13520772/2496794