dell公司网站设计特色,海南网站设计公司,at结尾网站,建筑工程网论坛网站部署在华为云服务器上#xff0c;Debian系统#xff0c;使用DjangoNginxuwsgi搭建。最终效果如下图所示。 一、响应逻辑顺序
1. 聊天页面请求
客户端请求/chat/#xff08;输入聊天室房间号界面#xff09;和/chat/room_name#xff08;某个聊天室页面#xff09;链…网站部署在华为云服务器上Debian系统使用DjangoNginxuwsgi搭建。最终效果如下图所示。 一、响应逻辑顺序
1. 聊天页面请求
客户端请求/chat/输入聊天室房间号界面和/chat/room_name某个聊天室页面链接时由Nginx转到Django由urls.py解析并返回相应页面在返回的聊天室页面内置了javascript程序请求建立wss:/ws/chat/room_name的websocket连接。
2. websocket连接请求
客户端向Nginx发送websocket连接请求根据Ngnix配置文件location /ws {}中设置的反向代理请求被转到本地的7001端口 http://127.0.0.1:7001将由运行在该端口上的由daphne托管的asgi服务解析并响应配置文件为myproject/asgi.py。
3. asgi.py解析并响应
asgi.py中定义的application定义了websocket的解析规则具体由/myproject/routing.py中的websocket_urlpatterns进行地址解析通过Channels由myapp/comsumers.py进行异步信息处理并响应。
二、配置Channels和asgi
1. 安装Channels
sudo pip3 install channels
2. settings.py中添加应用并配置channels和asgi
INSTALLED_APPS [django.contrib.auth,django.contrib.admin, django.contrib.contenttypes,django.contrib.sessions,django.contrib.messages,django.contrib.staticfiles,channels,myapp,
]ASGI_APPLICATION myproject.asgi.application# Channels_Layers相关配置
CHANNEL_LAYERS {default: {BACKEND: channels_redis.core.RedisChannelLayer,CONFIG: {hosts: [(127.0.0.1, 6379)],},},
}# 配置认证后端
AUTHENTICATION_BACKENDS (django.contrib.auth.backends.ModelBackend,
)
Django Channels利用 Redis 作为通道层来管理客户端和服务器之间的通信。当客户端通过 WebSocket 连接发送消息时Django Channels 会使用 Redis 将消息分发到所有连接的客户端。Redis 充当消息代理实时有效地处理消息的路由和传递。
ASGI_APPLICATION指向Django项目下的asgi.py文件中的application。
3. 配置asgi.py文件
import os
import django
os.environ.setdefault(DJANGO_SETTINGS_MODULE, myproject.settings)
django.setup()from django.core.asgi import get_asgi_application
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.auth import AuthMiddlewareStack
from myproject import routingsapplication ProtocolTypeRouter({http:get_asgi_application(), #支持http请求websocket:AuthMiddlewareStack(URLRouter(routings.websocket_urlpatterns) #支持webscoket请求),
})此处django.setup()和DJANGO_SETTINGS_MODULE设置应放在导入模块前否则容易出现如下报错
django.core.exceptions.AppRegistryNotReady: Apps arent loaded yet.
Requested setting DEBUG, but settings are not configured.
You must either define the environment variable DJANGO_SETTINGS_MODULE
or call settings.configure() before accessing settings... WSGI和ASGI 的主要区别是同步VS异步WSGI是同步的,每个请求必须等待前一个请求完成。而ASGI是异步的可以同时处理多个请求。 WSGI主要用于HTTP协议ASGI旨在支持WebSocket、HTTP2等协议。ASGI的主要特点是异步非阻塞它能够更好地处理并发请求。
上述设置中websocket地址解析由Django项目下的routings.py完成其功能与urls.py类似。
4. 配置routings.py
from django.urls import path
from myapp import consumerswebsocket_urlpatterns [path(rws/chat/str:room_name/, consumers.ChatConsumer.as_asgi())
] myapp为新建的应用其下的consumers.py文件定义了websocket的响应函数ChatConsumer。
5. 配置myapp/consumers.py
import json
from channels.generic.websocket import AsyncWebsocketConsumer
from asgiref.sync import sync_to_async
from myapp.models import ChatMessageclass ChatConsumer(AsyncWebsocketConsumer):async def connect(self):self.room_name self.scope[url_route][kwargs].get(room_name) #获取传输的房间号if self.room_name:self.room_group_name fchat_{self.room_name}# Join room groupawait self.channel_layer.group_add(self.room_group_name, self.channel_name)await self.accept()else:await self.close()async def disconnect(self, close_code):# Leave room groupawait self.channel_layer.group_discard(self.room_group_name, self.channel_name)# Receive message from WebSocketasync def receive(self, text_data):text_data_json json.loads(text_data)message text_data_json[message]username text_data_json[username]#保存消息await self.save_message(username, self.room_name, message)# 向群组内的所有客户端发送消息type为“chat_messageawait self.channel_layer.group_send(self.room_group_name, {type: chat_message, message: message,username:username})# Receive message from room groupasync def chat_message(self, event):message event[message]username event[username]# Send message to WebSocketawait self.send(text_datajson.dumps({message: message,username:username}))# 信息写入数据库sync_to_async()def save_message(self, username, room, message):if len(message) !0 :newmsg ChatMessage.objects.create(usernameusername, roomroom, contentmessage)newmsg.save()
文件中定义了websocket的连接消息的接收、发送和存储每条消息在发送给群组内的所有客户端前先存储到数据库。
三、消息存储
1. 配置myapp/models.py用于消息存储
from django.db import modelsclass ChatMessage(models.Model):username models.CharField(max_length100,verbose_name用户名)room models.CharField(max_length100)content models.TextField(verbose_name内容)create_time models.DateTimeField(auto_now_addTrue,verbose_name写入时间)def __str__(self):return f房间号:{self.room}--用户:{self.username}({self.content})
2. 配置myapp/admin.py便于在Django后台处理存储的消息
from django.contrib import admin# Register your models here.
from .models import ChatMessage
admin.site.register(ChatMessage) 效果如下 四、安装redis并启动
1. 安装redis
sudo apt-get install redis-server
安装后redis-server会自动启动可以使用sudo systemctl start/stop/restart/status redis.service来启动/停止/重启/查看服务器。
$sudo systemctl status redis.service ● redis-server.service - Advanced key-value storeLoaded: loaded (/lib/systemd/system/redis-server.service; enabled; vendor preset: enabled)Active: active (running) since Tue 2024-11-19 23:38:28 CST; 20h agoDocs: http://redis.io/documentation,man:redis-server(1)Main PID: 123767 (redis-server)Status: Ready to accept connectionsTasks: 5 (limit: 2321)Memory: 7.2MCPU: 1min 36.022sCGroup: /system.slice/redis-server.service└─123767 /usr/bin/redis-server 127.0.0.1:6379
五、安装daphne并启动asgi服务
1. 安装daphne Daphne 是 Django Channels 项目的一部分专门用于为 Django 提供支持 WebSocket和 ASGI 协议的异步服务器。
sudo pip3 install daphne
启动asgi服务的命令如下监听端口为7001。
daphne -p 7001 myproject.asgi:application
asgi服务的配置文件即为前面已经完成的asgi.py。
为了管理方便将其做成系统服务开机启动。
2. 设置daphne.service服务
新建/etc/systemd/system/daphne.service文件
sudo nano /etc/systemd/system/daphne.service
内容如下
[Unit]
DescriptionDaphne Server
Afternetwork.target[Service]
Typeexec
WorkingDirectory/home/yislwll/Django/myproject
ExecStart/usr/bin/daphne -p 7001 myproject.asgi:application
Restartalways
Useryislwll
GroupYisl
EnvironmentPYTHONPATH/home/yislwll/Django/myproject[Install]
WantedBymulti-user.target
然后启动daphne服务
sudo systemctl enable daphne.service
sudo systemctl start daphne.service
需要特别注意的是修改consumers.py文件后一定要重启daphne服务否则对websocket通讯内容的更改无法更新。
sudo systemctl restart daphne.service 六、配置Nginx
根据响应逻辑Ngnix应该对websocket的连接“wss://域名/ws/chat/room_name”做出响应请求将被代理到本地的7001端口由运行在该端口上由daphne托管的asgi服务解析并响应。
1. 配置/etc/nginx/nginx.conf
网站为https://连接所以webscoket连接为wss:// server {listen 443 ssl;server_name xxxx.com;charset utf-8;ssl_certificate /path/to/fullchain.pem; # SSL证书的路径ssl_certificate_key /path/to/privkey.pem; # 私钥的路径# SSL 配置ssl_session_timeout 1d;ssl_session_cache shared:MozSSL:10m; # about 4000 sessionsssl_session_tickets off;# 指定加密套件ssl_protocols TLSv1.2 TLSv1.3;ssl_ciphers xxxxxxxxx;ssl_prefer_server_ciphers on;location / {#由django响应uwsgi_pass 127.0.0.1:8080;include uwsgi_params;include /etc/nginx/uwsgi_params;uwsgi_param UWSGI_SCRIPT iCourse.wsgi;uwsgi_param UWSGI_CHDIR /iCourse;index index.html index.htm;client_max_body_size 35m;index index.html index.htm;}location /ws {#wss协议由asgi服务响应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:7001;proxy_set_header Upgrade $http_upgrade;proxy_set_header Connection upgrade;proxy_connect_timeout 300s;proxy_read_timeout 300s;proxy_send_timeout 300s; }}2. 重启Nginx服务
sudo systemctl restart nginx.service
七、客户端界面
1. 配置urls.py响应客户端界面请求
from myapp import views as channelsviewurlpatterns [......path(chat/,channelsview.chat, namewebchat),path(chat/str:room_name/, channelsview.chatroom, namechatroom),......
]
客户端页面请求将由myapp/views.py来处理。
2. 配置views.py
from django.shortcuts import render
from django.contrib.auth.decorators import login_required
from .models import ChatMessage# Create your views here.
login_required(login_url/login/)
def chat(request):return render(request,channels/chattingindex.html)login_required(login_url/login/)
def chatroom(request,room_name):username request.session.get(username,游客)msgs ChatMessage.objects.filter(roomroom_name).order_by(create_time)[0:20]return render(request,channels/chattingroom.html,{room_name:room_name,username:username, msgs:msgs})
在chatroom函数中对当前聊天室历史消息的最近20条进行了查询并由页面展示出来。
3. 聊天页面设计及通讯
chattingroom.html文件内容大致如下
{% extends newdesign/newbase.html %}{% load django_bootstrap5 %}{% block mytitle %}title{{room_name}}号聊天室/titlestyle.chat-window {max-width: 900px;height: 500px;overflow-y: scroll; /* 添加垂直滚动条 */margin: auto;background-color: #f1f1f1;border: 2px solid #09e3f7;border-radius: 5px;padding: 10px;}.chat-message {clear: both;overflow: hidden;margin-bottom: 10px;text-align: left;}.chat-message .message-content {border-radius: 5px;padding: 8px;max-width: 500px;float: left;clear: both;}.chat-message.right .message-content {background-color: #428bca;color: white;float: right;width:420px;}.chat-message.right .user-content {background-color: #f7e91d;border-radius:4px;color: black;float: right;width: auto;text-align: right;padding-left:10px;padding-right:10px;}.chat-message.left .message-content {background-color: #2ef3be;border-color: #ddd;float:left;width:420px;}.chat-message.left .user-content {background-color: #f7e91d;border-radius:4px;border-color: #ddd;float: left;width: auto;text-align: left;padding-left:8px;padding-right:8px;}/style{% endblock %}{% block maincontent %} div classcontainerdiv idchat-record classchat-window{% for m in msgs %}{% if m.username request.user.username %}div classchat-message rightdiv classuser-content{{m.username}}/divdiv classmessage-contentspan{{m.content}}/span/div/divbr{% else %}div classchat-message leftdiv classuser-content{{m.username}}/divdiv classmessage-contentspan{{m.content}}/span/div/divbr{% endif %}{% endfor %}/div/divbrdiv classmx-auto px-auto styletext-align: center;input idchat-message-input typetext stylewidth:900px; size150brbrinput idchat-message-submit typebutton value发送消息/div{{ room_name|json_script:room-name }}{{ username|json_script:username }}scriptwindow.onload function() {var scrollableDiv document.getElementById(chat-record);// 设置scrollTop使得滚动条向下翻scrollableDiv.scrollTop scrollableDiv.scrollHeight;};const roomName JSON.parse(document.getElementById(room-name).textContent);const username JSON.parse(document.getElementById(username).textContent);const chatSocket new WebSocket(wss://scybbd.com/ws/chat/ roomName /);chatSocket.onmessage function(e) {const data JSON.parse(e.data);//data为收到的后端发出来的数据console.log(data);if (data[message]) {if(data[username] username){document.querySelector(#chat-record).innerHTML (div classchat-message rightdiv classuser-content data[username] /divdiv classmessage-contentspan data[message] /span/div/divbr);}else{document.querySelector(#chat-record).innerHTML (div classchat-message leftdiv classuser-content data[username] /divdiv classmessage-contentspan data[message] /span/div/divbr);}} else {alert(消息为空)}var scrollableDiv document.getElementById(chat-record);// 设置scrollTop使得滚动条向下翻scrollableDiv.scrollTop scrollableDiv.scrollHeight;};chatSocket.onclose function(e) {console.error(聊天端口非正常关闭);};document.querySelector(#chat-message-input).focus();document.querySelector(#chat-message-input).onkeyup function(e) {if (e.keyCode 13) { // enter, returndocument.querySelector(#chat-message-submit).click();}};document.querySelector(#chat-message-submit).onclick function(e) {const messageInputDom document.querySelector(#chat-message-input);const message messageInputDom.value;chatSocket.send(JSON.stringify({message: message,username:username}));messageInputDom.value ;};/script
{% endblock %}聊天界面比较简陋客户端与服务器的wss://连接和通讯由页面中javacript脚本完成。
至此一个简单的多人在线聊天的页面基本完成。 文章转载自: http://www.morning.mrxqd.cn.gov.cn.mrxqd.cn http://www.morning.rtqyy.cn.gov.cn.rtqyy.cn http://www.morning.rdkt.cn.gov.cn.rdkt.cn http://www.morning.txrkq.cn.gov.cn.txrkq.cn http://www.morning.mwqbp.cn.gov.cn.mwqbp.cn http://www.morning.tqbyw.cn.gov.cn.tqbyw.cn http://www.morning.bpds.cn.gov.cn.bpds.cn http://www.morning.yqrfn.cn.gov.cn.yqrfn.cn http://www.morning.ubpsa.cn.gov.cn.ubpsa.cn http://www.morning.zwgrf.cn.gov.cn.zwgrf.cn http://www.morning.lxqyf.cn.gov.cn.lxqyf.cn http://www.morning.zcrjq.cn.gov.cn.zcrjq.cn http://www.morning.kpbgp.cn.gov.cn.kpbgp.cn http://www.morning.yqsq.cn.gov.cn.yqsq.cn http://www.morning.jcbjy.cn.gov.cn.jcbjy.cn http://www.morning.xfhms.cn.gov.cn.xfhms.cn http://www.morning.ypzsk.cn.gov.cn.ypzsk.cn http://www.morning.dhwyl.cn.gov.cn.dhwyl.cn http://www.morning.pngph.cn.gov.cn.pngph.cn http://www.morning.ljcf.cn.gov.cn.ljcf.cn http://www.morning.fbjqq.cn.gov.cn.fbjqq.cn http://www.morning.tqlhn.cn.gov.cn.tqlhn.cn http://www.morning.ksggr.cn.gov.cn.ksggr.cn http://www.morning.qllcp.cn.gov.cn.qllcp.cn http://www.morning.zrjzc.cn.gov.cn.zrjzc.cn http://www.morning.wanjia-sd.com.gov.cn.wanjia-sd.com http://www.morning.hwnnm.cn.gov.cn.hwnnm.cn http://www.morning.pumali.com.gov.cn.pumali.com http://www.morning.jfqqs.cn.gov.cn.jfqqs.cn http://www.morning.xnyfn.cn.gov.cn.xnyfn.cn http://www.morning.hydkd.cn.gov.cn.hydkd.cn http://www.morning.rmryl.cn.gov.cn.rmryl.cn http://www.morning.nngq.cn.gov.cn.nngq.cn http://www.morning.yrblz.cn.gov.cn.yrblz.cn http://www.morning.guangda11.cn.gov.cn.guangda11.cn http://www.morning.szzxqc.com.gov.cn.szzxqc.com http://www.morning.mtbth.cn.gov.cn.mtbth.cn http://www.morning.xnwjt.cn.gov.cn.xnwjt.cn http://www.morning.lhgkr.cn.gov.cn.lhgkr.cn http://www.morning.phnbd.cn.gov.cn.phnbd.cn http://www.morning.zwfgh.cn.gov.cn.zwfgh.cn http://www.morning.mdwtm.cn.gov.cn.mdwtm.cn http://www.morning.sffwz.cn.gov.cn.sffwz.cn http://www.morning.yccnj.cn.gov.cn.yccnj.cn http://www.morning.qfgxk.cn.gov.cn.qfgxk.cn http://www.morning.mbpzw.cn.gov.cn.mbpzw.cn http://www.morning.wpqwk.cn.gov.cn.wpqwk.cn http://www.morning.twwts.com.gov.cn.twwts.com http://www.morning.frxsl.cn.gov.cn.frxsl.cn http://www.morning.cnlmp.cn.gov.cn.cnlmp.cn http://www.morning.txfxy.cn.gov.cn.txfxy.cn http://www.morning.pjftk.cn.gov.cn.pjftk.cn http://www.morning.ckcjq.cn.gov.cn.ckcjq.cn http://www.morning.knpmj.cn.gov.cn.knpmj.cn http://www.morning.mpszk.cn.gov.cn.mpszk.cn http://www.morning.rfbpq.cn.gov.cn.rfbpq.cn http://www.morning.zlsmx.cn.gov.cn.zlsmx.cn http://www.morning.xyhql.cn.gov.cn.xyhql.cn http://www.morning.qwnqt.cn.gov.cn.qwnqt.cn http://www.morning.jfbrt.cn.gov.cn.jfbrt.cn http://www.morning.yskhj.cn.gov.cn.yskhj.cn http://www.morning.xwlhc.cn.gov.cn.xwlhc.cn http://www.morning.hwpcm.cn.gov.cn.hwpcm.cn http://www.morning.dxqwm.cn.gov.cn.dxqwm.cn http://www.morning.wmrgp.cn.gov.cn.wmrgp.cn http://www.morning.xfjwm.cn.gov.cn.xfjwm.cn http://www.morning.ydrml.cn.gov.cn.ydrml.cn http://www.morning.fpzz1.cn.gov.cn.fpzz1.cn http://www.morning.xsctd.cn.gov.cn.xsctd.cn http://www.morning.rnkq.cn.gov.cn.rnkq.cn http://www.morning.jjxnp.cn.gov.cn.jjxnp.cn http://www.morning.rmqlf.cn.gov.cn.rmqlf.cn http://www.morning.pjrgb.cn.gov.cn.pjrgb.cn http://www.morning.xdfkrd.cn.gov.cn.xdfkrd.cn http://www.morning.czxrg.cn.gov.cn.czxrg.cn http://www.morning.ymtbr.cn.gov.cn.ymtbr.cn http://www.morning.gxhqt.cn.gov.cn.gxhqt.cn http://www.morning.wnhml.cn.gov.cn.wnhml.cn http://www.morning.btrfm.cn.gov.cn.btrfm.cn http://www.morning.hrydl.cn.gov.cn.hrydl.cn