英文:
How can I fix the error of not being able to establish a connection to a Django Channels server with WebSockets using Python and ASGI?
问题
Django channels & websockets:无法建立与服务器的连接。
我正在尝试使用Django Channels、Websockets和p5创建实时绘图应用程序。
我唯一遇到的问题是:Firefox无法建立与服务器的连接,连接地址为ws://XXX.XXX.XXX.XXX:8090/ws/room/1/。
我所做的:
settings.py:
INSTALLED_APPS = [
...
'channels',
]
ASGI_APPLICATION = 'DrawMatch.asgi.application'
CHANNEL_LAYERS = {
'default': {
"BACKEND": "channels.layers.InMemoryChannelLayer"
}
}
asgi.py:
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'DrawMatch.settings')
django_asgi_app = get_asgi_application()
application = ProtocolTypeRouter({
"http": django_asgi_app,
"websocket": AllowedHostsOriginValidator(
AuthMiddlewareStack(
URLRouter(
drawmatch_app.routing.websocket_urlpatterns
)
)
),
})
consumers.py:
class DrawConsumer(AsyncJsonWebsocketConsumer):
room_code: str = None
room_group_name: str = None
async def connect(self):
self.room_code = self.scope['url_route']['kwargs']['room_code']
self.room_group_name = f'room_{self.room_code}'
print(f"room_code: {self.room_code}")
print(f"room_group_name: {self.room_group_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: str = None, _: Any = None) -> None:
data = json.loads(text_data)
await self.channel_layer.group_send(
self.room_group_name,
{
'type': 'draw',
'data': data
}
)
async def send_message(self, res):
await self.send(text_data=json.dumps({
"payload": res
}))
routing.py:
websocket_urlpatterns = [
url(r'^ws/room/(?P<room_code>\w+)/$', DrawConsumer.as_asgi()),
]
views.py:
def room(request, room_code):
context = {
'room_code': room_code
}
return render(request, 'room.html', context)
urls.py:
urlpatterns = [
path('', views.home),
...
path('room/<room_code>/', views.room),
path('predict', draw_guess.main),
]
room.html:
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<title>DrawMatch - Room {{ room_code }}</title>
<link rel="stylesheet" href="{% static 'styles/style.css' %}">
<script src="{% static 'scripts/index.mjs' %}" type="module"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0/p5.min.js"></script>
<script>
const csrftoken = '{{ csrf_token }}';
const room_code = {{ room_code }};
const connectionString = `ws://${window.location.host}/ws/room/{{room_code}}/`;
const gameSocket = new WebSocket(connectionString);
</script>
</head>
<body>
<h1>Room {{ room_code }}</h1>
<div class="drawings-container"></div>
</body>
</html>
index.js:
const WIDTH = 500;
const HEIGHT = 500;
const STROKE_WEIGHT = 3;
const drawingsContainer = document.querySelector(".drawings-container");
console.log(gameSocket);
gameSocket.onmessage = (e) => {
console.log(`Server: ${e.data}`)
const data = JSON.parse(e.data);
if (data.type === "draw") {
const {
canvas, x, y, px, py
} = data.data;
canvas.line(x, y, px, py);
}
}
gameSocket.onopen = (e) => {
console.log("Connected to websocket");
}
gameSocket.onclose = (e) => {
console.log("Disconnected from websocket");
}
function setupCanvas(canvas, id) {
console.log(connectionString);
let timeout;
let drawing = false;
canvas.setup = () => {
canvas.createCanvas(WIDTH, HEIGHT);
canvas.strokeWeight(STROKE_WEIGHT);
canvas.stroke("black");
canvas.background("#FFFFFF");
canvas.canvas.id = id;
drawingsContainer.appendChild(canvas.canvas);
}
canvas.draw = () => {
if (!drawing) return;
canvas.line(canvas.mouseX, canvas.mouseY, canvas.pmouseX, canvas.pmouseY);
if (timeout) return;
timeout = setTimeout(async () => {
const image = canvas.canvas.toDataURL();
const response = await fetch("/predict", {
method: "POST", body: JSON.stringify({
image
}), headers: {
"X-CSRFToken": csrftoken, "Content-Type": "application/json"
}
})
const data = await response.text();
console.log(data);
gameSocket.send(JSON.stringify({
type: "draw", data: {
canvas: canvas.id, x: canvas.mouseX, y: canvas.mouseY, px: canvas.pmouseX, py: canvas.pmouseY
}
}));
timeout = null;
}, 200);
}
canvas.mousePressed = () => drawing = canvas.mouseX > 0 && canvas.mouseX <= WIDTH && canvas.mouseY > 0 && canvas.mouseY <= HEIGHT;
canvas.mouseReleased = () => drawing = false
}
new p5(leftCanvas => {
setupCanvas(leftCanvas, "leftCanvas");
})
new p5(rightCanvas => {
setupCanvas(rightCanvas, "rightCanvas");
})
英文:
Django channels & websockets : can’t establish a connection to the server.
I am trying to do a real-time drawing app using django channels, websockets & p5.
The only problem I've got is : Firefox can’t establish a connection to the server at ws://XXX.XXX.XXX.XXX:8090/ws/room/1/.
What I've done :
settings.py :
INSTALLED_APPS = [
...
'channels',
]
ASGI_APPLICATION = 'DrawMatch.asgi.application'
CHANNEL_LAYERS = {
'default': {
"BACKEND": "channels.layers.InMemoryChannelLayer"
}
}
asgi.py :
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'DrawMatch.settings')
django_asgi_app = get_asgi_application()
application = ProtocolTypeRouter({
"http": django_asgi_app,
"websocket": AllowedHostsOriginValidator(
AuthMiddlewareStack(
URLRouter(
drawmatch_app.routing.websocket_urlpatterns
)
)
),
})
consumers.py :
class DrawConsumer(AsyncJsonWebsocketConsumer):
room_code: str = None
room_group_name: str = None
async def connect(self):
self.room_code = self.scope['url_route']['kwargs']['room_code']
self.room_group_name = f'room_{self.room_code}'
print(f"room_code: {self.room_code}")
print(f"room_group_name: {self.room_group_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: str = None, _: Any = None) -> None:
data = json.loads(text_data)
await self.channel_layer.group_send(
self.room_group_name,
{
'type': 'draw',
'data': data
}
)
async def send_message(self, res):
await self.send(text_data=json.dumps({
"payload": res
}))
routing.py :
websocket_urlpatterns = [
url(r'^ws/room/(?P<room_code>\w+)/$', DrawConsumer.as_asgi()),
]
views.py :
def room(request, room_code):
context = {
'room_code': room_code
}
return render(request, 'room.html', context)
urls.py :
urlpatterns = [
path('', views.home),
...
path('room/<room_code>/', views.room),
path('predict', draw_guess.main),
]
room.html :
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<title>DrawMatch - Room {{ room_code }}</title>
<link rel="stylesheet" href="{% static 'styles/style.css' %}">
<script src="{% static 'scripts/index.mjs' %}" type="module"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0/p5.min.js"></script>
<script>
const csrftoken = '{{ csrf_token }}';
const room_code = {{ room_code }};
const connectionString = `ws://${window.location.host}/ws/room/{{room_code}}/`;
const gameSocket = new WebSocket(connectionString);
</script>
</head>
<body>
<h1>Room {{ room_code }}</h1>
<div class="drawings-container"></div>
</body>
</html>
index.js :
const WIDTH = 500;
const HEIGHT = 500;
const STROKE_WEIGHT = 3;
const drawingsContainer = document.querySelector(".drawings-container");
console.log(gameSocket);
gameSocket.onmessage = (e) => {
console.log(`Server: ${e.data}`)
const data = JSON.parse(e.data);
if (data.type === "draw") {
const {
canvas, x, y, px, py
} = data.data;
canvas.line(x, y, px, py);
}
}
gameSocket.onopen = (e) => {
console.log("Connected to websocket");
}
gameSocket.onclose = (e) => {
console.log("Disconnected from websocket");
}
function setupCanvas(canvas, id) {
console.log(connectionString);
let timeout;
let drawing = false;
canvas.setup = () => {
canvas.createCanvas(WIDTH, HEIGHT);
canvas.strokeWeight(STROKE_WEIGHT);
canvas.stroke("black");
canvas.background("#FFFFFF");
canvas.canvas.id = id;
drawingsContainer.appendChild(canvas.canvas);
}
canvas.draw = () => {
if (!drawing) return;
canvas.line(canvas.mouseX, canvas.mouseY, canvas.pmouseX, canvas.pmouseY);
if (timeout) return;
timeout = setTimeout(async () => {
const image = canvas.canvas.toDataURL();
const response = await fetch("/predict", {
method: "POST", body: JSON.stringify({
image
}), headers: {
"X-CSRFToken": csrftoken, "Content-Type": "application/json"
}
})
const data = await response.text();
console.log(data);
gameSocket.send(JSON.stringify({
type: "draw", data: {
canvas: canvas.id, x: canvas.mouseX, y: canvas.mouseY, px: canvas.pmouseX, py: canvas.pmouseY
}
}));
timeout = null;
}, 200);
}
canvas.mousePressed = () => drawing = canvas.mouseX > 0 && canvas.mouseX <= WIDTH && canvas.mouseY > 0 && canvas.mouseY <= HEIGHT;
canvas.mouseReleased = () => drawing = false
}
new p5(leftCanvas => {
setupCanvas(leftCanvas, "leftCanvas");
})
new p5(rightCanvas => {
setupCanvas(rightCanvas, "rightCanvas");
})
答案1
得分: 1
问题出在routing.py文件中:
websocket_urlpatterns = [
url(r'^ws/room/(?P<room_code>\w+)/$', DrawConsumer.as_asgi()),
]
正确的版本是:
websocket_urlpatterns = [
path('ws/room/<room_code>/', DrawConsumer.as_asgi()),
]
英文:
The problem was in routing.py :
websocket_urlpatterns = [
url(r'^ws/room/(?P<room_code>\w+)/$', DrawConsumer.as_asgi()),
]
the correct version is :
websocket_urlpatterns = [
path('ws/room/<room_code>/', DrawConsumer.as_asgi()),
]
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论