最近完成的一個項目用到了websock+channels實現實時通信,這裏把本身的心得寫下來分享分享,但願能夠對有這方面的需求的朋友有所幫助。html
channels是django1.9之後纔出的一個新的特性,它容許Django以「通道模式」運行,經過創建通道層,來向消費者和生產者(消息發送者)之間傳遞消息。git
安裝channels:pip install channelsgithub
安裝channels所依賴的通道層(通常都是redis,也能夠是別的):pip install asgi_redisweb
在Django項目中配置channnels:redis
1.在settings文件的INSTALLED_APPS裏面加入channelsdjango
INSTALLED_APPS = [
. . .服務器
'channels',
]websocket
2.在settings文件中加入channels通道層的配置:異步
CHANNEL_LAYERS = {
"default": {
"BACKEND": "asgi_redis.RedisChannelLayer",
"CONFIG": {
"hosts":[("localhost", 6379)],
},
"ROUTING": "testchannels.routing.routing",
},
}socket
解釋一下這段代碼:它跟DATABASES的配置有點像,BACKEND指定channels通道層由redis實現。CONFIG是IP跟redis端口。ROUTING又叫通道路由,通道路由將通道映射到消費者函數。跟 urls.py相似,當有WebSocket請求訪問時,就會根據這個路徑找到相應表單,調用相應的函數進行處理,按照慣例通道路由應該在routing.py裏。
3.替換掉Django的基於HTTP/WSGI的請求處理器,而是使用通道。它是一個基於新興標準ASGI(異步服務器網關接口)的, 因此咱們將在asgi.py文件裏定義處理器:
上面的都配置完之後就能夠開始寫代碼了。
主要要建立2個文件——consumer.py,routing.py
routing.py:
當websocket創建鏈接時,會尋找websocket.connet,而後調用noGroupConsumer.ws_connect方法。
當websocket發送數據時,會尋找websocket.receive,而後調用noGroupConsumer.ws_receive方法。
當websocket斷開鏈接時,會尋找websocket.disconnect,而後調用noGroupConsumer.ws_disconnect方法。
而後建立個人consumer文件noGroupConsumer.py:
每行代碼什麼意思都標註清楚了,這裏就不作解釋了。
測試:運行項目,而後建立一個websocket鏈接發送消息。
鏈接websocket而後發送一個「hello world」,這時會彈一個框 hello world說明channels成功。
注意圖上畫紅圈的url跟routing裏面的對照一下。
Group
上面只是最基本的websocket+channels知識。若是有不少的websocket鏈接,可是他們須要收到不一樣的消息,怎麼處理呢?就好比A集合跟B集合兩個websocket鏈接集合。A集合中的任何一個元素髮了一條信息,全部元素都能收到,可是B集合根本不想收到A集合中元素髮的信息,怎麼辦呢?channels中的Group就是解決這個問題的——把信息發送到它須要的地方。
routing.py:
consumer:groupConsumer.py:
當創建鏈接後,把鏈接存入到Group中:Group("myRoom").add(message.reply_channel)
myRoom是Group的名字。Group("myRoom").send({"text":data})就會把數據發送到加入到myRoom裏面的鏈接。
咱們能夠改一下上面那個html代碼
跟以前惟一不一樣的就是websocket url須要加上組名(Group 的name)
Ok,這樣經過Group編碼也完成了,可是Group名是不能變的,如何動態的鏈接到各個Group呢?
其實能夠從message['path']裏面提取出Group的名字,而後把myRoom替換掉就行
代碼GitHub地址:https://github.com/shichaosc/gitskills/tree/master/jozzon