IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> django+channels(websocket)开发及nginx部署 -> 正文阅读

[Python知识库]django+channels(websocket)开发及nginx部署

作者:recommend-item-box type_blog clearfix

前言:因为项目中需要服务器实时将结果反馈给前端,之前采用的ajax轮询的方式,缺点大家都懂的。因为久仰websocket大名,正好最近有些时间,就想把原有项目升级一下,由ajax升级到websocket,毕竟websocket可以由服务器主动发送数据,优势太明显了。

这篇博文分为两个阶段,即开发配置与部署。其实开发(demo)只用了一会儿就完成了,并且在python manage.py runserver 下前后台测试成功,以为很快可以发布了。结果部署到生产环境中居然费了两天时间。因为之前没用过,所以费了好大的力气,特别是开始想用IIS的URL重写功能,结果研究了一天也没成功(本来用IIS+Django的案例就很少,加上channels就更少了,我可能还是哪里没设置好,如果有谁配置成功了希望能教教我),后来改用nginx也磨了大半天才成功。这里记录一下流程的步骤,以免将来遗忘。

各种版本:python--3.8.3? django--3.1.4? nginx--1.21.4? chanels--3.0.4??OS:window2012Server?

一,开发配置

1,安装channels:

? ? ? ? 因为新版django中已经淘汰了传统的websocket,将功能融入到了更全面的channels中,所以需要先在命令行安装channels

pip install channels

2,配置项目setting.py,首先注册一下channels

INSTALLED_APPS = [
   ...
    'channels',
   ...
]

? ? ? ? 再在原来指定WSGI的后面添加ASGI变量

WSGI_APPLICATION = 'heidanew.wsgi.application' #原项目中有的
ASGI_APPLICATION = 'heidanew.asgi.application' #新添加的,就是将wsgi都改成asgi

这里解释一下这两个名词:WSGI是基于HTTP协议模式的,不支持WebSocket,而ASGI的诞生则是为了解决Python常用的WSGI不支持当前Web开发中的一些新的协议标准。同时,ASGI对于WSGI原有的模式的支持和WebSocket的扩展,即ASGIWSGI的扩展。

3,修改asgi.py中的内容(django3以上应该都有这个文件,如果没有可以创建一个,与setting.py平级)如下:

import os
from django.core.asgi import get_asgi_application
from channels.routing import ProtocolTypeRouter, URLRouter
from . import routing
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'heidanew.settings')

application = ProtocolTypeRouter({
    "http":get_asgi_application(),
    "websocket": URLRouter(routing.websocket_urlpatterns)
})

因为默认的asgi中没有websocket协议,所以利用这个入口文件将websocket加进来,注意上面有一个from . import routing,现在还没有这个文件,所以按这个顺序走的时候那里会报错,一会儿我们就创建这个文件

4,与asgi.py平级的目录中新建routing.py文件,

我的代码如下:

from django.urls import re_path
from ws_app import consumers

websocket_urlpatterns=[
    re_path(r'ws/channels/',consumers.ChatConsumer.as_asgi())
]

routing.py相当于wsgi使用的urls.py,都是提供路由作用的。我这里只写了一个路径,你当然可以写多个路径。上面引入 的ws_app中的consumners,是下面即将要创建的app及其中的一个模块。

5, 用startapp命令创建一个ws_app的app,创建consumers.py文件(app名和文件名当然可以随意起名,但要和第4步中的引入对应上)

?consumers.py中的代码如下:

from channels.generic.websocket import WebsocketConsumer
from channels.exceptions import StopConsumer
class ChatConsumer(WebsocketConsumer):
    def websocket_connect(self, message):
        #有客户端向后端改善websocket请求时自动触发
        #服务端允许执行下行代码,如果不允许可以用 raise StopConsumner()拒绝客户端的连接请求
        self.accept()
    def websocket_receive(self, message):
        #客户端发来数据时触发,message是客户端发来的数据(一个字典)
        print(message)
        self.send("服务器端的内容")#向客户端发送数据
    def websocket_disconnect(self, message):
        # 断开连接时触发
        raise StopConsumer()

这里的三个“回调”函数分别分别连接成功时,接收客户端数据时,连接关闭时,函数名不能变,我这里每当接收到客户端请求时就自动发一个“服务端的内容”给客户端,而且你也可以在程序中任意位置使用self.send随时将数据主动发送给客户端。

二.,前端代码?

<body>
 
    <button onclick="sendData(123)">发送</button>
   
</body>
<script type="text/javascript">
    if ("WebSocket" in window) {
        // 打开一个 web socket      
        ws = new WebSocket("ws://127.0.0.1:7002/ws/channels/");

        // 连接建立后的回调函数
        ws.onopen = function() {
            // Web Socket 已连接上,使用 send() 方法发送数据
            ws.send("admin:123456");
            console.log("正在发送:admin:123456");
        };

        // 接收到服务器消息后的回调函数
        ws.onmessage = function(evt) {
            var received_msg = evt.data;
            if (received_msg.indexOf("sorry") == -1) {
                console.log("收到消息:" + received_msg);
            }

        };

        // 连接关闭后的回调函数
        ws.onclose = function() {
            // 关闭 websocket
            console.log("连接已关闭...");
        };
    } else {
        // 浏览器不支持 WebSocket
        console.log("您的浏览器不支持 WebSocket!");
    }
    // setTimeout(() => {
    //     ws.send("aaabbccc");
    //     console.log("正在发送:aabccc");

    // }, 1000)

    function sendData(str) {
        ws.send(str)
    }
</script>

现在,可以使用python manage.py runserver 7002开启测试服务器,打开前端网页时直接可以看到下图所示结果,就表示成功了

三,部署nginx服务器?

你觉得这样就够了?远远不行,因为思路为外网进来的时候是不可以使用这个测试(开发环境)w作为服务器的,需要绑定域名和使用daphne服务器进行托管asgi服务。思路如下:

进站域名如果是ws协议开头的,如ws://域名:7002/ws/channels/
则转换为ws://127.0.0.1:7002/ws/channels。此时的127.0.0.1:7002并不是nginx服务器,而是为ASGI提供服务的daphne程序。具体步骤如下:(以下操作均在远程服务器进行)

1,启动daphne服务:

在终端运行执行以下命令,启动127.0.0.1:7002的ASGI服务

daphne -p 7002 heidanew.asgi:application

启动后如下所示:

这里注意一下:这个daphne在官网上看是在unix环境下 运行的,但实际上我的操作系统是window也可以运行

2,nginx中的nginx.conf文件内容,其中的server配置这么写:

    server {
        listen       7002;
        server_name  你的域名;
        location / {#一般的http协议
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host  $http_host;
            proxy_set_header X-Nginx-Proxy true;
            proxy_set_header Connection "";
            proxy_pass http://域名:7001;
            proxy_redirect default;
            #root   html;
        }
          location /ws{#ws协议时
            proxy_http_version 1.1;
            proxy_set_header Host  $host;
            proxy_set_header X-Real-Ip $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Nginx-Proxy true;
            proxy_redirect off;
            client_max_body_size 10m;
            proxy_pass http://127.0.0.1:7002;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_connect_timeout 300s;
            proxy_read_timeout 300s;
            proxy_send_timeout 300s; 
       }
     
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }

说明一下,上面的代码将访问网站的请求分为2种,http(https)或ws(wss),前者直接走前面的请求,实际上我还有一个IIS服务器,是指向 “域名:7001"地址的,所以正常的请求就直接走7001这个地址即可即proxy_pass http://域名:7001,但如果是ws协议,则走的proxy_pass http://127.0.0.1:7002;运行的是本机的daphne服务。、

我在配置IIS时也想进行这种URL重写,但是不知为什么一直没有成功。以上就是配置的全部内容,现在在远程测试一下。将前端代码中的websocket对象在定义时改成你的域名,即:

ws = new WebSocket("ws://域名:7002/ws/channels/");

然后在本地运行(即访问远程服务器)应该可以得到下图的结果了。

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2021-12-11 15:40:40  更:2021-12-11 15:41:16 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/16 4:43:58-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码