注明
本笔记主要参考《Django应用开发实战》《Django企业开发实战》,这两本书前者详细,后者精炼。学习之后真的是感觉自己进步了很多。值得一读,如果您遇到了值得一读的书籍,欢迎推荐给我,大家共同进步。
@[TOC](文章目录)
前言
Web聊天室的实现方法有多种,下面将简要介绍一下实现方法
- AJAX技术利用AJAX实现网页与服务器的无刷新交互。缺点是实时性不高。
- Coment技术Coment是一种Web应用框架,服务器以异步方式向浏览器推送数据,无需浏览器发送请求,非常适合事件驱动的Web应用,以及对交互性和实时性要求较高的应用。
- XMPP协议:可扩展消息处理协议,专为及时通信系统设计的通信协议,用于即时消息以及在线探测
- Flash的XmlSocket:Flash Media Server 是一个强大的流媒体服务器,它基于RTMP协议,提供了稳定的流媒体交互功能,内置远程共享对象的机制,是浏览器创建并连接服务器的远程共享
- websocket协议:WebSocket是一种在单个TCP连接上进行全双工通信的协议WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket
API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输
django实现websocket大致上有两种方式,一种channels,一种是dwebsocket。channels依赖于redis,twisted等
提示:以下是本篇文章正文内容,下面案例可供参考
一、Channels?
Channels安装与配置
pip install channels
pip channels_redis
pip install pypiwin32
settings配置
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'channels',
'chat',
]
ASGI_APPLICATION = '项目名.routing.application'
CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels_redis.core.RedisChannelLayer',
'CONFIG': {
"hosts": [('127.0.0.1', 6379)],
},
},
}
说明:
- CHANNEL_LAYERS用于设置Redis数据库的连接方式.
- ASGI_APPLICATION:代表routing.py定义的application对象。
项目名文件夹下定义routing.py
from channels.routing import ProtocolTypeRouter
from channels.routing import URLRouter
from .urls import websocket_urlpatterns
application = ProtocolTypeRouter({
'websocket': AuthMiddlewareStack(
URLRouter(
websocket_urlpatterns
)
),
})
说明:
定义这个文件是为了响应ASGI_APPLICATION定义application对象,将Django与该插件建立连接。
在项目名文件夹下urls.py,定义websocket_urlpatterns
from django.urls import path, include
from .consumers import ChatConsumer
urlpatterns = [
path('', include(('chat.urls', 'chat'), namespace='chat'))
]
websocket_urlpatterns = [
path('ws/chat/<room_name>/', ChatConsumer),
]
说明:
- websocket_urlpatterns用于定义Channels的路由信息,上数定义的路由ws/chat/<room_name>/,它是由consumers.py的ChatConsumer处理和响应HTTP请求的,该路由作为Channels的API接口由网页的Javascript与该路由构建通信连接,使浏览器和服务器之间相互传递数据。
最后定义consumers.py
from channels.generic.websocket import AsyncWebsocketConsumer
import json
class ChatConsumer(AsyncWebsocketConsumer):
async def connect(self):
self.room_name = self.scope['url_route']['kwargs']['room_name']
self.room_group_name = 'chat_%s' % self.room_name
await self.channel_layer.group_add(
self.room_group_name,
self.channel_name
)
await self.accept()
async def disconnect(self, close_code):
await self.channel_layer.group_discard(
self.room_group_name,
self.channel_name
)
async def receive(self, text_data):
text_data_json = json.loads(text_data)
message = text_data_json['message']
await self.channel_layer.group_send(
self.room_group_name,
{
'type': 'chat_message',
'message': message
}
)
async def chat_message(self, event):
message = event['message']
await self.send(text_data=json.dumps({
'message': message
}))
下面可以很简单的实现在线聊天功能
大致思路:在应用urls中设置两个路由:创建聊天和进入聊天室。在创建聊天室后即跳转到进入聊天室路由。进入聊天室路由网页设置:使网页与项目插件连接,设置接收和发送信息(也可以设置异常事件触发器)。下面步骤
chat urls
from django.urls import path
from .views import *
urlpatterns = [
path('', newChat, name='newChat'),
path('<room_name>/', room, name='room'),
]
chat views
from django.shortcuts import render
def newChat(request):
return render(request, 'chat.html', locals())
def room(request, room_name):
return render(request, 'room.html', locals())
chat.html(截取部分重要)
<body>
<div>请输入聊天室名称</div>
<br/>
<input id="input" type="text" size="30"/>
<br/>
<input id="submit" type="button" value="进 入"/>
<script>
document.querySelector('#input').focus();
document.querySelector('#input').onkeyup = function(e) {
if (e.keyCode === 13) { // enter, return
document.querySelector('#submit').click();
}
};
document.querySelector('#submit').onclick = function(e) {
var roomName = document.querySelector('#input').value;
window.location.pathname = '/' + roomName + '/';
};
</script>
</body>
说明:
确定聊天室名称后,单击进入或者回车将触发javaScript脚本。
room.html
<body>
<textarea id="chat-log" cols="50" rows="6"></textarea>
<br/>
<input id="input" type="text" size="50"/><br/>
<input id="submit" type="button" value="发 送"/>
</body>
<script>
var roomName = '{{ room_name }}';
var chatSocket = new WebSocket(
'ws://' + window.location.host +
'/ws/chat/' + roomName + '/');
chatSocket.onmessage = function(e) {
var data = JSON.parse(e.data);
var message = data['message'];
document.querySelector('#chat-log').value += (message + '\n');
};
chatSocket.onclose = function(e) {
console.error('Chat socket closed unexpectedly');
};
document.querySelector('#input').focus();
document.querySelector('#input').onkeyup = function(e) {
if (e.keyCode === 13) { // enter, return
document.querySelector('#submit').click();
}
};
document.querySelector('#submit').onclick = function(e) {
var messageInputDom = document.querySelector('#input');
var message = messageInputDom.value;
chatSocket.send(JSON.stringify({
'message': message
}));
messageInputDom.value = '';
};
</script>
说明:
var chatSocket部分为了网页与项目插件连接
chatSocket.onmessage接收数据,并展示到文本框
chatSocket.onclose关闭连接,当出现异常时触发
document.querySelector发送数据
querySelector将文本展示到网页textarea组件中。
|