django channels에 해당하는 글 2

[2] 장고 채널스(django chennals) Group

Computer 비관심/Django|2017. 2. 17. 13:05
반응형

Group의 개념


urls의와 비슷한 개념의 routing.py에 이번에는 websocket.connect를 추가합니다.

websocket.receive는 소켓에 message가 전달 됬을때 발생하며

websocket.connect는 소켓에 소켓이 생성됬을 때 발생합니다. 

#routing.py

channel_routing = [
    route('websocket.receive','chat.consumers.ws_echo'),
    route('websocket.connect', 'chat.consumers.ws_add'),
]

그러면 consumers.py에서 ws_add를 만들고 그룹에 있는 사람들이 메시지를 모두 받을 수 있도록 ws_echo를 수정해 보겠습니다. 

이전 글에서도 말했듣이 consumers.py는 장고의 views.py와 비슷하다고 볼 수 있습니다.  


ws_add에서는 routing.py에 websocket.connect가 실행되면 Group('chat')이라는 객체를 만든뒤 웹소켓 연결을 통해 만들어진 인스턴스들을 추가합니다.


ws_echo도 Goup('chat').send({text:브라우저로 보낼내용})

# consumers.py

from channels import Group


def ws_add(message):
    Group('chat').add(message.reply_channel)


def ws_echo(message):
    Group('chat').send({
        'text': message.content['text'],
    })


소캣객체 생성부터 메시지보내기 까지 3번 반복~

for (var i = 0; i < 3; ++i) {
  // Create a new WebSocket
  var ws = new WebSocket((window.location.protocol == 'http:' ? 'ws://' : 'wss://') +  window.location.host + '/')
  // Assign it an id
  ws.id = i;
  // Make it show a console message when a message is received
  ws.onmessage = function(message) {
    console.log('W' + this.id + ': ' + message.data);
  }
  // Send a new message when the WebSocket opens
  ws.onopen = function() {
    this.send('Hello, world');
  }
}

소켓을 만들고 ws.onmessage 즉 메시지가 왔으면 console.log를 사용해 message.data의 내용을 console에 뿌려준다.

ws.send는 서버에 내용을 hellow,world를 전달해준다.

반응형

댓글()

[1] 장고 채널스(django channels) 웹소켓 에코

Computer 비관심/Django|2017. 2. 17. 10:28
반응형


장고 채널은 장고 1.10 이상에서 지원


1.설치

# requirements.txt

asgi-redis==1.0.0
channels==0.17.3
daphne==0.15.0
Django==1.10.4

requirements.txt 파일을 만든 뒤 pip install -r requirements.txt를 입력하여 requirements.txt에 있는 모듈을 모두 설치 한다.




2. 앱 세팅


- 프로젝트를 만들고 앱을 만든다. 


- settings.py의 INSTALLED_APPS에 channels와 새로 생성한 앱 추가한다. (여기선 앱의 이름을 chat 이라고 만듬)

# settings.py

INSTALLED_APPS = (
    ...
    'channels',
    'chat',
)

...

CHANNEL_LAYERS = {
    'default': {
        'BACKEND': 'asgiref.inmemory.ChannelLayer',
        'ROUTING': 'django_channels.routing.channel_routing',
    },
}

3.routing


- 라우팅 처리를 위하여 위에 설정한 바와 같이 django_channels라는 폴더에 routing.py 파일을 만든다.  


# routing.py
from channels.routing import route

channel_routing = [
    route('websocket.receive', 'chat.consumers.ws_echo'),
]

4. consumers.py


# consumers.py

def ws_echo(message):
    message.reply_channel.send({
        'text': message.content['text'],
    })


소켓이 접속이 되는지 확인하기 위해 로컬호스트에 접속하여 소켓을 만들어 아래를 입력합니다.


// http인지 https인지 확인 하여 그것에 맞는 소켓을 웹소켓 프로토콜을 선택
var ws_scheme = window.location.protocol == "https:" ? "wss" : "ws";
ws = new WebSocket(ws_scheme +'://' +  window.location.host + '/');


이렇게 소켓에 접속 된 것을 볼수 있습니다.


// Create a new WebSocket
ws = new WebSocket((window.location.protocol == 'http:' ? 'ws://' : 'wss://') +  window.location.host + '/')

// ws.onmessage를 통해 메시지를 받으면 알림
ws.onmessage = function(message) {
  alert(message.data); 
}
// ws.onpen을 통해 소켓이 열리면 메시지를 보냄
ws.onopen = function() {
  ws.send('Hello, world');
}

send의 키를 text라고 하고 키 값으로 브라우저에 보낼 내용을 적습니다. 아래의 예는 브라우저에서 보낸 내용을 매개변수 message로 받아 오브젝트를 생성하여 .content['text']로 브라우저에서 보낸 내용을 다시 브라우저에 전달 하였습니다.


content 딕셔너리의 text라는 키가 있음. 그 키에는 브라우저에서 보내온 값이 있다.


message오브젝트에 data속성에 채널에서 보낸 내용이 들어 있다.


ws.readyState 를 통해 소켓의 상태를 확인 할 수 있음.  

WebSocket.OPEN  ->1 반환 소켓이 열려있음 

WebSocket.CLOSED ->3 반환 소켓이 닫힘


※ 이대로 하면 websocket.receive이 작동안됨을 알 수 있다. 이유는 다음과 같다.

위의 모듈대로 설치하게 되면  Twisted 가 최신버전으로 깔리게 되는데 Twisted 16.2.0만 제대로 작동한다는 이야기가 있다.

즉, 제대로 작동하기 위해서는 Twisted를 지운뒤 16.2.0버전으로 다시 설치하여야 한다.





참고


글이 적어서 좋았던 튜토리얼

https://www.sourcelair.com/blog/articles/115/django-channels-chat

소켓연결에서 http와 https에 따른 ws와 wss 선택  

https://blog.heroku.com/in_deep_with_django_channels_the_future_of_real_time_apps_in_django

채널 공식 문서

https://media.readthedocs.org/pdf/channels/latest/channels.pdf

twisted 문제 

http://stackoverflow.com/questions/38322197/django-channels-websocket-receive-is-not-handled



반응형

댓글()