django-private-chat2 在线聊天室(django+websocket+nginx)

django-private-chat2是一个Django聊天应用程序,由 Django Channels、Websockets 和 Asyncio 提供支持,已经封装好了一些简单的聊天逻辑:包括 监听连接/断开 websocket,监听发送/接收 websocket消息,获取用户 对话框列表/消息列表等。 github地址:https://github.com/Bearle/django_private_chat2/ 如果这个库够用直接按照说明使用即可。我这里因为要扩展实现自己的逻辑,所以自定义了一个模块chat。实现如下:

一.、准备工作:

(1)安装django:pip install django==3.2.20 django版本需要大于3.0,因为需要ASGI的支持;我这里使用的是3.2.20版本。

(2)安装channels:pip install channels==3.0.4 Channels 是一个采用 Django 并将其功能扩展到 HTTP 之外的项目,用于处理 WebSocket。

(3)安装channel-redis:pip install channels-redis==3.3.1 channels_redis是唯一支持生产使用的由 Django 维护的官方通道层。该层使用 Redis 作为后备存储,支持单服务器和分片配置以及组支持。

(4)安装django-private-chat2:pip install django-private-chat2==1.0.2

(5)安装daphne:pip install daphne==3.0.2 daphne将请求从客户端转发到 Django Channels 或其他ASGI应用,并将响应返回到客户端。

为什么需要使用daphne: 生产环境部署中,使用的是WSGI协议来启动的我们的项目,也就是使用的wsgi.py这个文件来对接的uWSGI服务器。但是channels使用的ASGI协议,在我们使用uWSGI来启动项目的时候,关于ASGI的一些配置他就找不到了。这就导致了所有的websocket请求都是404。 这个问题的解决有两种方案: 1)启用uWSGI来处理所有的http请求,另外开启一个daphne服务来处理websocket请求。这样的好处是按照请求类型分流,两种请求方式互不干扰。(亲测成功) 命令:daphne -p 4001 dingdang168.asgi:application 2)另外一种则是启用daphne服务来处理http和websocket这两种请求。在daphne服务内部他会根据请求类型的不同分开处理。让你既可以访问websocket又可以访问http。 这里采取第一种方法。

二、新增模块chat:

首先在项目根目录下执行:

python manage.py startapp chat

并依次执行以下步骤:

将django-private-chat2下所有的目录文件copy到chat模块下。 将chat模块下所有对django_private_chat2的引用改为chat。例如: from django_private_chat2.models 改为 from chat.models from django_private_chat2.serializers 改为 from chat.serializers

三、修改settings.py:

(1) 将channels和chat加入到INSTALLED_APPS里,并添加相应配置,如下所示:

INSTALLED_APPS = [

#···,

'daphne', # 放在比较靠前位置

#···,

'channels', # channels应用

'chat', # chat模块

]

(2)设置ASGI应用:

ASGI_APPLICATION = '项目名称.asgi.application'

(3)设置通道层的通信后台:

CHANNEL_LAYERS = {

# 开发环境

# 'default': {

#'BACKEND': 'channels.layers.InMemoryChannelLayer'

# }

# 生产环境

'default': {

'BACKEND': 'channels_redis.core.RedisChannelLayer',

'CONFIG': {

"hosts": ["redis://:password@127.0.0.1:6379/3"], # password改成自己的密码

},

}

四、新建asgi.py文件,与wsgi.py同级:

from django.core.asgi import get_asgi_application

django_asgi_app = get_asgi_application()

from channels.routing import ProtocolTypeRouter, URLRouter

from channels.auth import AuthMiddlewareStack

from chat import urls

application = ProtocolTypeRouter({

# http请求

"http": django_asgi_app,

# websocket请求

"websocket": AuthMiddlewareStack(

URLRouter(urls.websocket_urlpatterns)

),

})

五、nginx配置文件中添加:

server{

# ···

location /chat_ws {

proxy_pass http://127.0.0.1:4001; # asgi的端口

proxy_http_version 1.1;

# 将http连接升级成websocket的连接。

proxy_set_header Upgrade $http_upgrade;

# 启用支持websocket连接

proxy_set_header Connection "upgrade";

# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

# proxy_set_header X-Real-IP $remote_addr;

}

# ···

}

六、重启相关服务:

重启nginx: nginx -s reload #重新加载配置启动asgi服务: daphne -p 4001 项目名称.asgi:application

七、测试连接:

使用postman测试连接:

状态码101,表示websocket连接成功。

注意:

如果是在开发环境下,第五、六步骤可以直接省略,因为使用runserver命令启动时会直接启动asgi,如下图所示提示即表示启动成功。 ws和wss的关系类似于HTTP和HTTPS。wss 表示在 TLS 之上的 Websocket。WSS提供了加密通信,而WS没有。如果websocket请求需要传递额外的参数,例如token,可以放入请求头的Sec-WebSocket-Protocol中,用","隔开即可如果报错Error during WebSocket handshake: Sent non-empty ‘Sec-WebSocket-Protocol’ header but no response was received,意思是WebSocket握手阶段出错:发送了非空“Sec-WebSocket-Protocol”请求头但是响应中没有此字段 解决方法: 添加响应头Sec-WebSocket-Protocol,值设置为请求头Sec-WebSocket-Protocol的第一个协议 将chat_consumer.py中的await self.accept()改为await self.accept(protocol[0])。

有错误或者遗漏的地方,欢迎指正交流!

参考链接:

https://blog.csdn.net/qq_42902997/article/details/131558930 https://blog.csdn.net/ZPeng_Yan/article/details/106198365 https://channels.readthedocs.io/en/latest/introduction.html

精彩内容

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: