Use Channels to achieve WebSocket protocol

WebSocket protocol and HTTP protocol

Introduction to the HTTP protocol

It refers to the HTTP protocol Hypertext Transfer Protocol ( H yper T EXT T ransfer P rotocol), is transmitted from a web server to a hypertext transfer protocol the local browser, the application layer protocol is based on the TCP / IP protocol.

main feature

  1. Simple and fast : a customer service request to the server, instead of sending the request method and path, the communication speed quickly.
  2. Flexible : HTTP allows the transmission of any type of data object.
  3. Connectionless : each connection restriction process only one request. After the server processes client requests and receives the customer's response, i.e., disconnected. In this way it can save transmission time.
  4. Stateless : HTTP protocol is stateless protocol. No state is no protocol for transaction processing and memory. If the lack of state means that the subsequent processing required in front of the information, it must be retransmitted, which may result in the amount of data transmitted for each connection is increased. On the other hand, when it does not require previous information in response to a faster server.
  5. Supports client / server model

working principle

HTTP is based on client / server model, and connection-oriented. A typical HTTP transaction has the following process:

  1. Customers to establish a connection to the server;

    1. Customer request to the server;
    2. Server accepts the request and returns the corresponding file according to a request as a reply;
    3. Client and server closes the connection.

WebSocket Protocol Overview

Now, many sites in order to achieve push technology, the technology used is Ajax polling. Polling is in a specific time interval (e.g., every 1 second), issues an HTTP request to the server by the browser, and returns the latest data to the client browser by the server. This traditional model brings obvious disadvantage that the browser requires constant request to the server, however, HTTP requests may contain a long head, which truly effective data may only be a small part, obviously this will waste a lot of bandwidth resources.

HTML5 WebSocket protocol definition, better able to save server resources and bandwidth, and can be more real-time communication.

WebSocket is a protocol for full duplex communication over a single TCP connection. WebSocket enables exchange of data between the client and the server easier, allowing the server actively push data to the client . In the WebSocket API, the browser and the server only needs to complete a handshake, directly between the two can create a persistent connection , and two-way data transmission .

Django Channels WebSocket achieve real-time communication

Official Documents

Channels is a function using Django and expand the project to other than HTTP, to handle the WebSocket protocol. It is based on called ASGI the Python build specification.

Next, based on the use of official Tutorial1-2 brief Channels.

First you need to install Django and Channels

pip install django
pip install channels

Create a Django project and enter the project root directory:

django-admin startproject mysite
cd mysite

Next, create the root of routing Channels routing.py, channels routing configuration similar to Django URLconf, it tells Channels Channels When the server receives what code to run when the HTTP request.

First, an empty routing configuration from the start, create a file mysite/routing.pythat contains the following code:

# mysite/routing.py
from channels.routing import ProtocolTypeRouter

application = ProtocolTypeRouter({
    # (http->django views is added by default)
})

Then Channels library to register in the app list:

# mysite/settings.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    # 新添加
    'channels',
]

Continue to edit mtsite/settings.pythe Channels to the root routing configuration, add the following code:

# mysite/settings.py
# Channels
ASGI_APPLICATION = 'mysite.routing.application'

Channels can be controlled at this time runservercommand, instead of the standard developed by Channels server Django development server.

Run Django project:

py manage.py runserver

You will see the following output:

Performing system checks...

System check identified no issues (0 silenced).

You have 17 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.
March 07, 2020 - 22:45:04
Django version 3.0.2, using settings 'mysite.settings'
Starting ASGI/Channels version 2.4.0 development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
HTTP GET / 200 [0.04, 127.0.0.1:54871]

It can be seen Starting ASGI/Channels development server at http://127.0.0.1:8000/, indicating Channels development server from Django development server to take over the project. Open the initial screen , you will see the familiar small rocket:

Shut down the server, create App event:

py manage.py startapp event

Register app:

# mysite/settings.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'channels',
    # 新添加
    'event',
]

In the root directory create a new folder templatesand the templates/eventfolder to place html file, mysite/settings.pyadd the path:

# mysite/settings.py
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        # 修改
        'DIRS': [os.path.join(BASE_DIR, 'templates').replace('\\', '/')],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

In templatesadding the view file event/list.html, wherein the requested portion WebSocket template as follows:

<script type="text/javascript">
	function Filter() {
        if ("WebSocket" in window) {
            //alert("您的浏览器支持WebSocket!");
            // 重定向URL
            let ws = new WebSocket("ws://"+ window.location.host + "/ws/event/list/");
            ws.onopen = function () {
                ws.send(JSON.stringify({
                    'message': "测试",
                    // 需要传输的数据
                }));
            }
            ws.onmessage = function (evt) {
                let received_msg = JSON.parse(evt.data);
                let feed_back = received_msg['feedback'];
                alert(feedback);
                // 处理接受数据
            }
            ws.onclose = function () {
                //alert("WebSocket连接已关闭...");
            }
        }
        else {
            alert("你的浏览器不支持WebSocket!");
        }
    }
</script>

Create a view function event/views.py:

# event/views.py
from django.shortcuts import render

def list(request):
    return render(request, 'event/list.html', {})

Create a route event/urls.py:

# event/urls.py
from django.urls import path

from . import views

urlpatterns = [
    path('list/', views.list, name='list'),
]

Will event appadd the route to the root route project:

# mysite/urls.py
from django.conf.urls import include
from django.urls import path
from django.contrib import admin

urlpatterns = [
    path('admin/', admin.site.urls),
    path('event/', include('event.urls', namespace='event')),
]

Channels processing of the request:

1. Channels接受HTTP请求
2. 查询根URLconf查找**消费者(consumer)**
3. 在**消费者(consumer)**中调用各种功能来处理连接的事件

Create a consumer (consumer) file event/consumers.py:

event/
    __init__.py
    ……
    consumers.py
    ……
    urls.py
    views.py

Code templates are as follows:

# event/consumers.py
from channels.generic.websocket import WebsocketConsumer
import json

class ListDataConsumer(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']
        # 数据处理
        self.send(text_data=json.dumps({
        'feedback': "Accept",
        # 返回数据
    }))

Is consumers.pyconfigured to route new event/routing.py:

# event/routing.py
from django.urls import re_path

from . import consumers

websocket_urlpatterns = [
    re_path(r'ws/event/list/$', consumers.ListDataConsumer),
]

Then the root route points to event/routing.pythe file:

# mysite/routing.py
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter

import event.routing

application = ProtocolTypeRouter({
    # (http->django views is added by default)
    'websocket': AuthMiddlewareStack(
        URLRouter(
            event.routing.websocket_urlpatterns
        )
    ),
})

This routing configuration root specified when establishing a connection to the server Channels development, ProtocolTypeRouterwill first check the type of connection. If it is WebSocket connection ( WS: // or WSS: // ), assigned to the connection AuthMiddlewareStack.

In AuthMiddlewareStackthe filling connection of the range to cover the current user authentication and then connect to URLRouter. This URLRouterwill be based on research, to provide connectivity to route HTTP path to a particular consumer-based urlmodel.

After migrating database model:

py manage.py makemigrations
py manage.py migrate

Run the project:

py manage.py runserver

If the connection is established, the background should have the following display:

HTTP GET /event/list/ 200 [0.06, 127.0.0.1:58855]
WebSocket HANDSHAKING /ws/event/list/ [127.0.0.1:58906]
WebSocket CONNECT /ws/event/list/ [127.0.0.1:58906]

to sum up

Channels use the above general procedure, the following configuration ASGI, Channels server will replace the original Django server processes the request.

Only when required for use WebSocket protocol for real-time communication needs to be configured routing.pyand consumers.py, by the routing.pypoint consumers.pyprocessing WebSocket request, using only the remaining HTTP protocol requests before use and there is no difference .

Because only one app at a project in the use of the Channels, you can refer to the project code of event.

Guess you like

Origin www.cnblogs.com/liyishan/p/12624106.html