Django 基於channels實現群聊功能
后端框架
django
默認不支持 websocket
第三方模塊: channelsflask
默認不支持 websocket
第三方模塊: geventwebsockettornado
默認支持 websocket
下載 channel s模塊需要注意的點
1 版本不要用最新版 推薦使用 2.3 版本即可,如果你安裝最新版可能會出現自動將你本地的django 版本升級為最新版
2 python 解釋器建議使用 3.6 版本(3.5 可能會有問題,3.7 可能會有問題 具體說明問題沒有給解釋)
pip3 install channles==2.3
channels 模塊內部幫你封裝了握手/加密/解密等所有操作
基本使用
- 注冊 app
INSTALLED_APPS = [ 'channels' ]
注冊完成后,django 會無法啟動,會直接報錯
CommandError: You have not set ASGI_APPLICATION, which is needed to run the server.
- 配置
ASGI_APPLICATION = 's13_day01.routing.application' ASGI_APPLICATION = '項目名同名的文件名.文件夾下py文件名默認就叫routing.該py文件內部的變量名默認就叫application'
- 去項目名同名的文件夾下面新建一個 routing.py 文件,定義 application 變量
from channels.routing import ProtocolTypeRouter,URLRouter from django.conf.urls import url from app01 import consumers application = ProtocolTypeRouter({ 'websocket':URLRouter([ # websocket相關的路由 url(r'^chat/',consumers.ChatConsumer) ]) })
上述操作配置完成后,啟動 django 會由原來的 wsgiref 啟動變成 asgi 啟動(內部:達芙妮)
並且啟動之后 django 即支持 websocket 也支持 http 協議
基於 http 的操作還是在 urls.py 和 views.py 中完成
基於 websocket 的操作則在 routing.py 和 consumer.py (對應的應用中創建)中完成
from channels.generic.websocket import WebsocketConsumer class ChatConsumer(WebsocketConsumer): def websocket_connect(self, message): """客戶端請求建立鏈接時 自動觸發""" pass def websocket_receive(self, message): """客戶端發送數據過來 自動觸發""" pass def websocket_disconnect(self, message): """客戶端斷開鏈接之后 自動觸發""" pass
""" http協議 index路徑 index視圖函數 訪問:瀏覽器窗口直接輸入的地址的 websocket協議 chat路徑 ChatConsumer視圖類 訪問:new WebSocket對象訪問 """
方法總結
# 后端 3個 from channels.generic.websocket import WebsocketConsumer from channels.exceptions import StopConsumer consumer_object_list = [] class ChatConsumer(WebsocketConsumer): def websocket_connect(self, message): """客戶端請求建立鏈接時 自動觸發""" # print('請求鏈接') self.accept() # 建立鏈接 並且自動幫你維護每一個客戶端 # 將鏈接在列表中存儲一份 consumer_object_list.append(self) def websocket_receive(self, message): """客戶端發送數據過來 自動觸發""" # print(message) # message = {'type': 'websocket.receive', 'text': 'hello world!'} text = message.get('text') # 真正的數據 # 給客戶端發送消息 單獨發送 # self.send(text_data=text) # 給所有的鏈接對象發送數據 for obj in consumer_object_list: obj.send(text_data=text) def websocket_disconnect(self, message): """客戶端斷開鏈接之后 自動觸發""" # print('斷開鏈接') # 客戶端斷開鏈接之后 應該將當前對象移除 consumer_object_list.remove(self) raise StopConsumer() # 前端 4個 var ws = new WebSocket('ws://127.0.0.1:8000/chat/'); // 1 握手環節驗證成功之后 自動觸發 onopen ws.onopen = function () { console.log('握手成功') } // 2 給服務端發送消息 send function sendMsg() { ws.send($('#txt').val()) } // 3 一旦服務端有消息 自動觸發 onmessage ws.onmessage = function (args) { // console.log(args) // args是一個對象 // 獲取發送的數據 console.log(args.data) } // 4 斷開鏈接之后 自動觸發 onclose ws.onclose = function () { ws.close() }
群聊功能
我們是通過自己維護一個列表存儲鏈接對象的方式完成了簡易版本的群聊
其實 channels 給你提供了一個用於做群聊的模塊,該模塊可以實現真正的分組聊天