1、简介 http
(无状态、短连接)是不能由服务器主动向客户端发送请求,展示信息的。
我们要想实现一个人发了信息,能够实时展示在其它人的页面,有以下的方法。
WebSocket
是一种协议,设计用于提供低延时、==全双工==和长期运行的连接。
==轮询==(大量的请求与响应)
==长轮询==(频繁的建立和关闭连接)
WebSocket
的优势
双向实时通信
允许在单个、长时间的连接上进行双向实时通信。在需要快速实时更新的应用程序中,比http
更加高效
降低延迟
链接一旦建立就会保持开放,数据可以在客户端和服务器之间以比http
更低的延迟进行传输
更高效的资源利用
可以减少重复请求和响应的开销,因为它的链接只需要建立一次
2、心跳机制
3、限制
不提供加密功能
不支持古老的浏览器
优化很重要
保持长连接需要服务器不断地维护和处理连接状态,需要优化性能
4、Django
==Django
默认不支持WebSocket
,需要进行配置==
4.1、下载channels
库和daphne
库 1 python -m pip install -U channels["daphne"]
4.2、配置setting.py
文件 在setting.py
进行注册
1 2 3 4 5 6 INSTALLED_APPS = [ 'daphne', ··· ··· 'channels', ]
配置ASGI_APPLICATION
1 2 3 4 5 6 7 8 ASGI_APPLICATION = '项目名.asgi.application' 使用下面这个帮助我们管理多人聊天 CHANNEL_LAYERS = { "default": { "BACKEND": "channels.layers.InMemoryChannelLayer", } }
4.3、验证 启动django
服务,若出现以下内容则表示配置成功
4.4、修改asgi.py
文件 1 2 3 4 5 6 7 8 from channels.routing import ProtocolTypeRouter, URLRouter from . import routing application = ProtocolTypeRouter({ 'http': get_asgi_application(), 'websocket': URLRouter(websocket_urlpatterns), })
4.5、创建ws
路由 创建websocket
服务端文件consumers.py
文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 from channels.generic.websocket import AsyncWebsocketConsumer #异步方法 class MyConsumer(AsyncWebsocketConsumer): async def connect(self): await self.accept() async def disconnect(self, close_code): pass async def receive(self, text_data): await self.send(text_data) # 同步方式,仅作示例,不使用 class SyncConsumer(WebsocketConsumer): def connect(self): self.accept() def disconnect(self, close_code): pass # 从WebSocket中接收消息 def receive(self, text_data=None, bytes_data=None): pass
4.6、创建routing.py
文件 1 2 3 4 5 6 from django.urls import re_path from . import consumers websocket_urlpatterns = [ re_path(r'websocket/$', consumers.MyConsumer.as_asgi()), ]
4.7、编写前端页面的websocket
1 2 3 4 5 var socket = new WebSocket("ws:127.0.0.1:8000/websocket/"); socket.onopen = function () { console.log('连接成功');//成功连接上Websocket };
5、示例 5.1、前端 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 <!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <meta name ="viewport" content ="width=device-width, initial-scale=1.0" > <title > myserver</title > </head > <body > <div class ="message" id ="message" > </div > <div > <input type ="text" placeholder ="请输入" id ="txt" > <input type ="button" value ="发送" onclick ="sendMessage()" > </div > <script > socket = new WebSocket ("ws://127.0.0.1:8000/room/123" ) socket.onopen = function ( ) { socket.send ('hello,world!' ) } socket.onmessage = function (event ) { let tag = document .createElement ('div' ) tag.innerText = event.data document .getElementById ('message' ).appendChild (tag) } function sendMessage ( ) { let tag = document .getElementById ('txt' ) socket.send (tag.value ) } </script > </body > </html >
5.2、后端 项目目录
routing.py
1 2 3 4 5 6 7 8 from django.urls import re_pathfrom myapp import consumerswebsocket_urlpatterns = [ re_path(r"room/123" , consumers.ChatConsumer.as_asgi()), ]
consumers.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 from channels.generic.websocket import WebsocketConsumerfrom channels.exceptions import StopConsumerfrom asgiref.sync import async_to_syncimport timeimport requestsclass ChatConsumer (WebsocketConsumer ): def websocket_connect (self, message ): self.accept() def websocket_receive (self, msg ): print (msg['text' ]) self.send('hello,bupt' ) def websocket_disconnect (self, message ): raise StopConsumer()
asgi.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import osfrom django.core.asgi import get_asgi_applicationfrom channels.routing import ProtocolTypeRouter, URLRouterfrom . import routingos.environ.setdefault('DJANGO_SETTINGS_MODULE' , 'myserver.settings' ) application = ProtocolTypeRouter({ "http" : get_asgi_application(), "websocket" : URLRouter(routing.websocket_urlpatterns) })
6、参考文献 https://blog.csdn.net/qq_46042132/article/details/130994781