작성
·
64
·
수정됨
0
똑같이 코딩한거같은데 Uncaught InvalidStateError: Failed to execute 'send' on 'WebSocket': Still in CONNECTING
이런 문제가 생겨 connect()에서 console.log로 this.ws 찍어보니까. readystate가 0에서 바뀌지 않고 onsubmit()에서도 0인걸 확인했습니다. 그래서 웹소켓이 연결되지 않았으니, this.ws.send()에서 걸리는것이라고 생각은하는데, 어디를 고쳐야 될지 모르겠습니다.
{# Chat room #}
{% extends "chat/base.html" %}
{% block extra-style %}
<style>
.chat-message > div {
background-color: #3b3b3b;
color: #e1e1e1;
border-radius: 0.8em;
padding: 0.4em;
margin: 0.4em 0;
display: inline-block;
white-space: pre-wrap;
max-width: 80%;
word-wrap: break-word;
}
</style>
{% endblock %}
{% block content %}
<h2>채팅방 :{{ room_name }}</h2>
{# 웹소켓으로 실시간 채팅 기능 구현하기 #}
<div class="container">
<div class="row">
<div class="col-sm-12">
<div class="card" style="height: 600px;">
<div class="card-header">
채팅방:{{ room_name }}
</div>
<div class="card-body overflow-hidden">
<div id="chat_messages" class="w-100 h-100 border-0 overflow-hidden overflow-scroll"></div>
</div>
<div class="card-footer">
<form id="message_form">
<input type="text" name="message" class="form-control"
autofocus autocomplete="off" />
</form>
</div>
</div>
<hr class="my-3" />
<a href="{% url 'chat:index' %}" class="btn btn-primary"> 대기실로 이동 </a>
</div>
</div>
</div>
{% endblock %}
{% block extra-script %}
<script>
const handler = {
chat_messages_tag: null,
ws: null,
retry: 0,
init(){
console.log("handler.init() 실행됨");
this.chat_messages_tag= document.querySelector("#chat_messages");
document.querySelector("#message_form").addEventListener("submit", this.onsubmit.bind(this));
},
connect(ws_url){
if(this.ws) {
this.ws.close();
}
this.ws = new WebSocket(ws_url || this.ws?.url);
console.log(this.ws, "연결1.")
this.ws.onopen = this.onopen.bind(this);
this.ws.onclose = this.onclose.bind(this);
this.ws.onerror = this.onerror.bind(this);
this.ws.onmessage = this.onmessage.bind(this);
},
reconnect()
{
this.connect();
},
onopen(){
console.log("웹소켓 서버와 접속, : Room_chat");
this.retry = 0;
},
onclose(event){
if (!event.wasClean) {
console.error("웹소켓이 죽었거나, 네트워크 에러");
if (this.retry < 3)
{
this.retry++;
setTimeout(() => {
this.reconnect();
console.log(`[${this.retry}] 접속 재시도 ...`);
}, 1000 * this.retry)
}
else
{
console.log("웹소켓 서버에 접속할수 없습니다. 메인페이지로 이동합니다.");
window.location.href = "{% url 'chat:index' %}";
}
}
},
onerror(){
console.log("웹소켓 에러 발생. 메인페이지로 이동합니다.");
window.location.href = "{% url 'chat:index' %}" ;
},
onmessage(event){
const message_json = event.data;
console.log("메세지 수신 :", message_json);
const { type, message } = JSON.parse(message_json);
switch (type){
case "chat.message":
this.append_message(message);
break;
default:
console.error('Invalid message type: &{type}');
}
},
append_message(message){//인자로 받은 채팅 메세지 로그에 추가
const element = document.createElement("div");
element.className = "chat-message";
const wrapper = document.createElement("div");
wrapper.textContent = message;
element.appendChild(wrapper);
this.chat_messages_tag.appendChild(element);
this.chat_messages_tag.scrollTop = this.chat_messages_tag.scrollHeight;
},
onsubmit(event){ //입력된 채팅 메세지 문자열을 획득하고, 메세지 로그에 추가.
event.preventDefault();
const form_data = new FormData(event.target); //폼필드의 값을 오브젝트로 변환하여 props로 저장하고, 폼필드는 리셋합니다.
const props = Object.fromEntries(form_data);
event.target.reset(); // reset form
const { message } = props;
console.log("웹소켓으로 전송할 메세지: ", message);
console.log(this.ws, "onsubmit");
{#this.append_message(message);#}
this.ws.send(JSON.stringify({
type: "chat.message",
message: message,
}))
}
};
handler.init();
const protocol = location.protocol === 'https:' ? 'ws:' : 'wss:';
const ws_url = protocol + "//" + location.host + "/ws" + location.pathname;
handler.connect(ws_url);
</script>
{% endblock %}
from django.urls import path
from chat import consumers
websocket_urlpatterns = [
path("ws/chat/<str:room_name>/chat/", consumers.ChatConsumer.as_asgi()),
]
import os
from channels.routing import ProtocolTypeRouter, URLRouter
from django.core.asgi import get_asgi_application
import app.routing
import chat.routing
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings')
django_asgi_app = get_asgi_application()
application = ProtocolTypeRouter({
"http" : django_asgi_app,
"websocket" : URLRouter(
chat.routing.websocket_urlpatterns + app.routing.websocket_urlpatterns,
)
})
from django.shortcuts import render
# Create your views here.
def index(request):
return render(request, "chat/index.html")
def room_chat(request, room_name):
return render(request, "chat/room_chat.html",{
"room_name": room_name,
})
답변 2
1
안녕하세요.
서버 쪽 로그를 봐야 명확할 듯 싶습니다.
서버 쪽 에러 로그를 스크린샷으로 보여주시겠어요?
그리고 현재 프로젝트를 help@pyhub.kr 메일로 첨부로 보내주시면, 저도 실행해서 동작을 확인해보겠습니다.
오. 다행입니다.
장고 서버가 구동되었으니 asgiref 설치 문제는 아닐 듯 하구요.
말씀하신 대로 웹소켓 접속 scheme를 잘못 쓰셔서, 다른 프로토콜로 요청을 해서 서버에서 요청을 못 받은 듯 합니다. :-)
잘 찾으셨습니다. 👍
0
선생님 해결했습니다. 일단 두가지 정도 문제였던것 같습니다.
첫째로 asgiref가 제대로 설치되지 않았던것같고,
둘째로
const protocol = location.protocol === 'http:' ? 'ws:' : 'wss:'; const ws_url = protocol + "//" + location.host + "/ws" + location.pathname; handler.connect(ws_url);
여기서 'http:' ? 'ws:' : 'wss:';가 아니라 https로 작성해서 그랬던것같습니다. 위와 같은 이유가 맞을까요..?
같이 고민해주셔서 감사합니다.