最近项目中需要用到websocket,先写个小demo了解一下基础使用。
理论知识
1、uWSGI和Daphne uWSGI和Daphne是两个不同的Web服务器,它们都可以用于运行Django应用程序,但在不同的环境和场景下使用。
- uWSGI: uWSGI是一个全功能的Web服务器,它支持多种协议和接口规范,包括WSGI、FastCGI、HTTP等。它可以作为独立的Web服务器运行,也可以与其他Web服务器(如Nginx)配合使用。uWSGI可以处理WSGI应用程序的请求和响应,并提供了一些高级功能,如负载均衡、多进程管理和缓存等。在传统的Web应用程序中,uWSGI通常被用作生产环境的Web服务器。
- Daphne: Daphne是基于ASGI(Asynchronous Server Gateway Interface)规范的Web服务器,它专门用于运行异步Web应用程序,如Django Channels。ASGI是一种更加通用的接口规范,允许Web应用程序处理异步请求和响应,包括WebSocket连接、长轮询和服务器推送等。Daphne是Django Channels官方推荐的服务器,它可以在支持ASGI的环境中使用。在需要处理实时通信的Django应用程序中,Daphne是常用的选择。 综上所述,uWSGI是一个全功能的Web服务器,可以用于运行传统的WSGI应用程序,而Daphne是专用于运行基于ASGI的异步Web应用程序的服务器,如Django Channels。选择使用哪个服务器取决于你的应用程序的特性和需求。
2、asgi和wsgi WSGI(Web Server Gateway Interface)和ASGI(Asynchronous Server Gateway Interface)都是Python Web应用程序与Web服务器之间的接口标准,用于处理HTTP请求和响应。
- WSGI: WSGI是Python Web应用程序的标准接口,旨在定义Web应用程序和Web服务器之间的通信协议。它使用简单的函数调用来处理请求和生成响应。WSGI应用程序接收一个包含请求信息的字典作为参数,并返回一个包含响应信息的可迭代对象。WSGI服务器负责将请求信息传递给WSGI应用程序,并将响应发送回客户端。
- ASGI: ASGI是一种新一代的Python Web应用程序接口,专注于支持异步(asynchronous)和高性能的Web应用程序。它允许Web应用程序使用异步编程模型,例如使用async/await关键字和异步IO操作。ASGI应用程序接收一个包含请求信息的对象作为参数,并返回一个包含响应信息的对象。ASGI服务器负责将请求信息传递给ASGI应用程序,并将响应发送回客户端。 虽然WSGI在过去是Python Web应用程序的主要接口标准,但随着异步编程的兴起和对高性能的需求,ASGI逐渐受到重视并得到广泛应用。ASGI允许开发者使用异步框架(如Django Channels)来处理实时通信、长轮询等场景。
版本
django==4.2.4
channels==4.0.0
daphne==4.0.0
Channels是一个采用Django并将其能力扩展到HTTP之外的项目,用于处理WebSockets、聊天协议、物联网协议等。它建立在ASGI的Python规范之上。
Daphne是Django软件基金会开发的一个基于ASGI (HTTP/WebSocket)的服务器,可以用来启动我们的应用,因为默认启动方式是WSGI。
# 在settings.py同级目录增加文件asgi.py
import os
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
from django.core.asgi import get_asgi_application
from wsdemo.routing import websocket_urlpatterns
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "djangoProject1.settings")
# application = get_asgi_application()
application = ProtocolTypeRouter({
"http": get_asgi_application(),
'websocket': AuthMiddlewareStack(URLRouter(websocket_urlpatterns)),
})
# settings.py
INSTALLED_APPS = [
...
'daphne',
'channels',
'wsdemo'
...
]
# 添加
ASGI_APPLICATION = 'djangoProject1.asgi.application'
# 添加
CHANNEL_LAYERS = {
"default": {
"BACKEND": "channels.layers.InMemoryChannelLayer", # 使用内存通道层作为示例,实际使用时可以根据需要选择合适的后端
},
}
在wsdemo的app里添加文件下面的文件
#consumer.py
import json
from channels.generic.websocket import WebsocketConsumer
class ChatConsumer(WebsocketConsumer):
def connect(self):
self.accept()
def disconnect(self, close_code):
pass
def receive(self, text_data):
# text_data_json = json.loads(text_data)
# message = text_data_json["message"]
# 设置ensure_ascii以支持中文
self.send(text_data=json.dumps({"message111": text_data}, ensure_ascii=False))
#routing.py
import json
from channels.generic.websocket import WebsocketConsumer
class ChatConsumer(WebsocketConsumer):
def connect(self):
self.accept()
def disconnect(self, close_code):
pass
def receive(self, text_data):
# text_data_json = json.loads(text_data)
# message = text_data_json["message"]
# 设置ensure_ascii以支持中文
self.send(text_data=json.dumps({"message111": text_data}, ensure_ascii=False))
# template/index.html
<!DOCTYPE html>
<html>
<head>
<title>WebSocket Example</title>
</head>
<body>
<input type="text" id="messageInput" placeholder="Enter message">
<button onclick="sendMessage()">Send</button>
<ul id="messageList"></ul>
<script>
var ws = new WebSocket('ws://localhost:8999/ws/chat/');
ws.onopen = function() {
console.log('WebSocket connected');
// 在连接成功后执行的操作
};
ws.onmessage = function(event) {
console.log('Received message:', event.data);
// 处理接收到的消息
var messageList = document.getElementById('messageList');
var li = document.createElement('li');
li.innerText = event.data;
messageList.appendChild(li);
};
ws.onclose = function() {
console.log('WebSocket disconnected');
// 在连接关闭后执行的操作
};
function sendMessage() {
var messageInput = document.getElementById('messageInput');
var message = messageInput.value;
ws.send(message);
messageInput.value = ''; // 清空输入框
}
</script>
</body>
</html>
启动项目 daphne -p 8999 djangoProject1.asgi:application
在浏览器运行index.html文件