WebSocket长连接


WebSocket长连接

1、概述

image-20211111155015888

image-20211111155202002

1.1 定义

image-20211111160606614

1.2 原理

image-20211111162538141

2、Django中配置WebSocket

2.1安装第三方法包

  • pip install channels
    

2.2 Django 中的配置

  • Settings中的配置
    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'app01.apps.App01Config',
        'channels',#注册APP
    ]
    
  • 添加配置
    • 定位到Django3中的asgi.py下的application
    ASGI_APPLICATION = "djangoWS.asgi.application"
    
    • 修改asgy.py文件
    • 默认只支持http协议,修改其内容使得即支持HTTP又要支持WebSocket;
    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', 'djangoWS.settings')
    # 默认只支持http请求
    # application = get_asgi_application()
    
    application=ProtocolTypeRouter({
        "http":get_asgi_application(),
        "websocket":URLRouter(routing.websocket_urlpatterns),
    })
    
    
  • Settings.py的同级目录下,创建routing.py;

    # -*- coding: utf-8 -*-
    '''
    @Time    : 2021/11/12 9:00
    @Author  : ziqingbaojian
    @File    : routing.py
    '''
    
    from django.urls import re_path
    from app01 import consumers
    
    websocket_urlpatterns=[
        re_path(r'ws/?P\w+/$',consumers.ShowNum.as_asgi())
    ]
    
  • app01下创建consumers.py,编写处理事务的逻辑。

    # -*- coding: utf-8 -*-
    '''
    @Time    : 2021/11/12 9:11
    @Author  : ziqingbaojian
    @File    : consumers.py
    '''
    from channels.generic.websocket import WebsocketConsumer
    from channels.exceptions import StopConsumer
    
    
    # 继承WebsocketConsumer
    class ShowNum(WebsocketConsumer):
        def websocket_connect(self, message):
            # 有客户端来向后端发送WebSocket连接请求时,自动触发
            # 允许客户端的连接
            self.accept()
            # raise StopConsumer()# 不创建连接,直接使用raise将异常抛出;
    
        def websocket_receive(self, message):
            # 基于WebSocket想后端发送数据,自动触发接收数据
            # 接收到前端传回的消息
            self.send("不要回答,不要回答,不要回答")
    
        def websocket_disconnect(self, message):
            # 客户端与服务端断开连接时,自动触发
            raise StopConsumer()
    

2.3 django中需要了解的

  • wsgi:django3以前django属于同步的,wsgi是处理Socket
  • asgi : 相当于wsgi+异步+WebSocket
  • 普通启动,默认使用的是wsgi**

    image-20211112093454845

  • 基于asgi/channels启动

    image-20211112093744090

3、聊天室

  • 访问到地址界面,http请求

  • 让客户端向服务端主动发送websocket连接,服务端收到连接后(握手)。

    • 前端
    //websocket的协议,发送数据要带ws相当于,http请求以http开头一样;
    socket= new WebSocket("ws://127.0.0.1:8001/ws/123/")
    
    • 服务端
    from channels.generic.websocket import WebsocketConsumer
    from channels.exceptions import StopConsumer
    
    # 继承WebsocketConsumer
    class ShowNum(WebsocketConsumer):
        def websocket_connect(self, message):
            # 有客户端来向后端发送WebSocket连接请求时,自动触发
            # 允许客户端的连接(握手)
            print("连接来拉")
            self.accept()
            '''两次请求,连接一次握手一次'''
            # raise StopConsumer()# 不创建连接,直接使用raise将异常抛出;
    

3.1 收发消息( 客户端-->服务端)

  • 客户端
    
    
    
        
        Title
        
    
    
    
  • 服务端
    # -*- coding: utf-8 -*-
    '''
    @Time    : 2021/11/12 9:11
    @Author  : ziqingbaojian
    @File    : consumers.py
    '''
    from channels.generic.websocket import WebsocketConsumer
    from channels.exceptions import StopConsumer
    
    # 继承WebsocketConsumer
    class ShowNum(WebsocketConsumer):
    
        def websocket_receive(self, message):
            # 基于WebSocket想后端发送数据,自动触发接收数据
            # 接收到前端传回的消息
            print(message)
            self.send("不要回答,不要回答,不要回答")
    

    image-20211112102841586

3.2 收发消息(服务端-->客户端)

  • 服务端
    from channels.generic.websocket import WebsocketConsumer
    from channels.exceptions import StopConsumer
    
    
    # 继承WebsocketConsumer
    class ShowNum(WebsocketConsumer):
        def websocket_connect(self, message):
            # 有客户端来向后端发送WebSocket连接请求时,自动触发
            # 允许客户端的连接(握手)
            print("连接来拉")
            self.accept()
            '''两次请求,连接一次握手一次'''
            # raise StopConsumer()# 不创建连接,直接使用raise将异常抛出;
            # 服务端给客户端发送消息
            self.send("来了呀,哈哈哈")
    
    
  • 客户端
    
    

3.2 前端补充回调函数


3.3 关闭连接

  • 客户端主动关闭
    • 客户端
    
    
    
        
        Title
        
    
    
    
    • 服务端
    # -*- coding: utf-8 -*-
    from channels.generic.websocket import WebsocketConsumer
    from channels.exceptions import StopConsumer
    
    # 继承WebsocketConsumer
    class ShowNum(WebsocketConsumer):
    
        def websocket_disconnect(self, message):
            # 客户端与服务端断开连接时,自动触发
            print("断开连接了")
            raise StopConsumer()
    
  • 服务端主动关闭连接
    • 服务端
    from channels.generic.websocket import WebsocketConsumer
    from channels.exceptions import StopConsumer
    
    
    # 继承WebsocketConsumer
    class ShowNum(WebsocketConsumer):
    
    
        def websocket_receive(self, message):
            # 基于WebSocket想后端发送数据,自动触发接收数据
            # 接收到前端传回的消息
            print(message)
            text=message['text']
            print(text)
            self.send("不要回答,不要回答,不要回答")
            if text=="close":
                # 法一
                self.close()# 会触发前端的onCllose方法;
                return # 不在执行后期的代码
                # 法二
                # raise StopConsumer()# 如果服务端断开连接时,执行了StopConsumer异常,那么websocket_disconnect方法不在执行;
     
    
    • 客户端
    
    

3.4 整合代码示例

  • 服务端
    from channels.generic.websocket import WebsocketConsumer
    from channels.exceptions import StopConsumer
    
    # 继承WebsocketConsumer
    class ShowNum(WebsocketConsumer):
        def websocket_connect(self, message):
            # 有客户端来向后端发送WebSocket连接请求时,自动触发
            # 允许客户端的连接(握手)
            print("连接来拉")
            self.accept()
            '''两次请求,连接一次握手一次'''
            # raise StopConsumer()# 不创建连接,直接使用raise将异常抛出;
            # 服务端给客户端发送消息
            self.send("来了呀,哈哈哈")
    
        def websocket_receive(self, message):
            # 基于WebSocket想后端发送数据,自动触发接收数据
            # 接收到前端传回的消息
            print(message)
            text=message['text']
            print(text)
            self.send("不要回答,不要回答,不要回答")
            if text=="close":
                # 法一
                self.close()# 会触发前端的onCllose方法;
                return # 不在执行后期的代码
                # 法二
                # raise StopConsumer()# 如果服务端断开连接时,执行了StopConsumer异常,那么websocket_disconnect方法不在执行;
        def websocket_disconnect(self, message):
            # 客户端与服务端断开连接时,自动触发,包括关闭页面与浏览器的情况
            print("断开连接了")
            raise StopConsumer()
    
  • 客户端
    
    
    
        
        Title
        
    
    
    

3.5 群聊功能

  • 配置django中的配置文件或者,自定义设置连接池

4 、vue中使用Webscoket

  • 参考文献1:

  • 参考文献2 :

  • 方法一
    
    
    
    
    
    
  • 方法二