WebSocket长连接

1、概述

1.1 定义

1.2 原理

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<group>\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**

  • 基于asgi/channels启动

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 收发消息( 客户端-->服务端)

  • 客户端
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
    .top{
    height: 300px;
    width: 100%;
    border: 1px solid #ddd;
    }
    </style>
    </head>
    <body>
    <div class="top"></div>
    <input type="text" placeholder="请输入" id="txt">
    <button onclick="sendMessage()">发送</button>
    <script>
    //websocket的协议,发送数据要带ws相当于,http请求以http开头一样;
    socket= new WebSocket("ws://127.0.0.1:8001/ws/123/")
    function sendMessage(){
    var tag=document.getElementById("txt");
    socket.send(tag.value);
    }
    </script>
    </body>
    </html>
  • 服务端
    # -*- 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("不要回答,不要回答,不要回答")

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("来了呀,哈哈哈")
  • 客户端
    <script>
    //websocket的协议,发送数据要带ws相当于,http请求以http开头一样;
    socket= new WebSocket("ws://127.0.0.1:8001/ws/123/")
    function sendMessage(){
    var tag=document.getElementById("txt");
    socket.send(tag.value);
    }
    //当websocket接收到服务端发送来的消息的时候会自动触发这个函数
    socket.onmessage=function (event){
    console.log(event.data)
    } </script>

3.2 前端补充回调函数

<script>
//创建好连接之后自动触发(服务端执行完(self.accpet()之后会立即执行)
socket.onopen=function(event){
let tag= document.createElement("div");
tag.innerText="连接成功";
document.getElementById("top").appendChild(tag);
}
//连接成功之后进行提示
</script>

3.3 关闭连接

  • 客户端主动关闭
    • 客户端
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
    .top{
    height: 300px;
    width: 100%;
    border: 1px solid #ddd;
    }
    </style>
    </head>
    <body>
    <div class="top"></div>
    <input type="text" placeholder="请输入" id="txt">
    <button onclick="sendMessage()">发送</button>
    <button onclick="closeConn()">关闭连接</button> <script>
    //websocket的协议,发送数据要带ws相当于,http请求以http开头一样;
    socket= new WebSocket("ws://127.0.0.1:8001/ws/123/")
    function sendMessage(){
    var tag=document.getElementById("txt");
    socket.send(tag.value);
    } //当websocket接收到服务端发送来的消息的时候会自动触发这个函数
    socket.onmessage=function (event){
    console.log(event.data)
    }
    function closeConn(){
    socket.close();//向服务端发送断开连接的请求
    }
    </script>
    </body>
    </html>
    • 服务端
    # -*- 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方法不在执行;
    • 客户端
    <script>
    //websocket的协议,发送数据要带ws相当于,http请求以http开头一样;
    socket= new WebSocket("ws://127.0.0.1:8001/ws/123/")
    function sendMessage(){
    var tag=document.getElementById("txt");
    socket.send(tag.value);
    }
    //服务端主动断开连接的时候会被触发
    socket.onclose=function (event){
    console.log("连接已断开")
    }
    </script>

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()
  • 客户端
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
    .top{
    height: 300px;
    width: 100%;
    border: 1px solid #ddd;
    }
    </style>
    </head>
    <body>
    <div class="top"></div>
    <input type="text" placeholder="请输入" id="txt">
    <button onclick="sendMessage()">发送</button>
    <button onclick="closeConn()">关闭连接</button>
    <script>
    //websocket的协议,发送数据要带ws相当于,http请求以http开头一样;
    socket= new WebSocket("ws://127.0.0.1:8001/ws/123/")
    function sendMessage(){
    var tag=document.getElementById("txt");
    socket.send(tag.value);
    }
    //服务端主动断开连接的时候会被触发
    socket.onclose=function (event){
    console.log("连接已断开")
    } //当websocket接收到服务端发送来的消息的时候会自动触发这个函数
    socket.onmessage=function (event){
    console.log(event.data)
    }
    function closeConn(){
    socket.close();//向服务端发送断开连的请求
    }
    </script>
    </body>
    </html>

3.5 群聊功能

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

4 、vue中使用Webscoket

  • 参考文献1:https://www.cnblogs.com/niuben/p/14607900.html

  • 参考文献2 :https://www.cnblogs.com/qisi007/p/10213886.html

  • 方法一
    <template>
    <div class="test"> </div>
    </template> <script>
    export default {
    name : 'test',
    data() {
    return {
    websock: null,
    }
    },
    created() {
    this.initWebSocket();
    },
    destroyed() {
    this.websock.close() //离开路由之后断开websocket连接
    },
    methods: {
    initWebSocket(){ //初始化weosocket
    if()
    const wsuri = "ws://127.0.0.1:8080";
    this.websock = new WebSocket(wsuri);
    this.websock.onmessage = this.websocketonmessage;
    this.websock.onopen = this.websocketonopen;
    this.websock.onerror = this.websocketonerror;
    this.websock.onclose = this.websocketclose;
    },
    websocketonopen(){ //连接建立之后执行send方法发送数据
    let actions = {"test":"12345"};
    this.websocketsend(JSON.stringify(actions));
    },
    websocketonerror(){//连接建立失败重连
    this.initWebSocket();
    },
    websocketonmessage(e){ //数据接收
    const redata = JSON.parse(e.data);
    },
    websocketsend(Data){//数据发送
    this.websock.send(Data);
    },
    websocketclose(e){ //关闭
    console.log('断开连接',e);
    },
    },
    }
    </script>
    <style lang='less'> </style>
  • 方法二
    <template>
    <div>
    <button @click="send">发消息</button>
    </div>
    </template> <script>
    export default {
    data () {
    return {
    path:"ws://192.168.0.200:8005/qrCodePage/ID=1/refreshTime=5",
    socket:""
    }
    },
    mounted () {
    // 初始化
    this.init()
    },
    methods: {
    init: function () {
    if(typeof(WebSocket) === "undefined"){
    alert("您的浏览器不支持socket")
    }else{
    // 实例化socket
    this.socket = new WebSocket(this.path)
    // 监听socket连接
    this.socket.onopen = this.open
    // 监听socket错误信息
    this.socket.onerror = this.error
    // 监听socket消息
    this.socket.onmessage = this.getMessage
    }
    },
    open: function () {
    console.log("socket连接成功")
    },
    error: function () {
    console.log("连接错误")
    },
    getMessage: function (msg) {
    console.log(msg.data)
    },
    send: function () {
    this.socket.send(params)
    },
    close: function () {
    console.log("socket已经关闭")
    }
    },
    destroyed () {
    // 销毁监听
    this.socket.onclose = this.close
    }
    }
    </script> <style> </style>

WebSocket长连接的更多相关文章

  1. 当web应用包含了websocket长连接,如何在web应用前加一层nginx转发

    1 通过在web应用的前面加一层nginx ,可以实现一台主机部署多个应用,每个应用都可以用不同的域名去访问,并且端口都是80 2 nignx 转发websocket长连接 1 每个web应用,他们运 ...

  2. 实现单台测试机6万websocket长连接

    本文由作者郑银燕授权网易云社区发布. 本文是我在测试过程中的记录,实现了单台测试机发起最大的websocket长连接数.在一台测试机上,连接到一个远程服务时的本地端口是有限的.根据TCP/IP协议,由 ...

  3. Spring+Stomp+ActiveMq实现websocket长连接

    stomp.js+spring+sockjs+activemq实现websocket长连接,使用java配置. pom.xml(只列出除了spring基本依赖意外的依赖,spring-version为 ...

  4. Python WebSocket长连接心跳与短连接

    python websocket 安装 pip install websocket-client 先来看一下,长连接调用方式: ws = websocket.WebSocketApp("ws ...

  5. WebSocket 长连接 及超时问题解决

    <?phpset_time_limit(0); class SocketService { private $address = 'localhost'; private $port = 80; ...

  6. 雨露均沾的OkHttp—WebSocket长连接的使用&源码解析

    前言 最近老板又来新需求了,要做一个物联网相关的app,其中有个需求是客户端需要收发服务器不定期发出的消息. 内心OS:

  7. Django websocket 长连接使用

    下载  pip install dwebsocket WebSocket是一种在单个TCP连接上进行全双工通信的协议 WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客 ...

  8. 微信小程序 实现websocket长连接 以及断开连接之后自动重连

    app.js let socketMsgQueue = [] let isLoading = false App({ globalData: { userInfo: null, localSocket ...

  9. Browser 與 Server 持續同步的作法介紹 (Polling, Comet, Long Polling, WebSocket)长连接

    對 Comet 的懵懂 記得兩年多前,第一次看到 Gmail 中的 GTalk 覺得很好奇:「咦?線上聊天且是 Google 的熱門系統,只用傳統的 AJAX 應該會操爆伺服器吧?」很幸運的,當時前公 ...

随机推荐

  1. a-b转换A-B

  2. 『无为则无心』Python基础 — 43、文件备份的实现

    目录 1.需求 2.步骤 3.代码实现 (1)接收用户输入目标文件名 (2)规划备份文件名 (3)备份文件写入数据 (4)思考 (5)完整编码 4.再来一个小练习 1.需求 用户输入当前目录下任意文件 ...

  3. python 如何获取当前系统的时间

    1.导入包 import datetime 2.获取当前的时间 curr_time = datetime.datetime.now() # 2019-07-06 14:55:56.873893 < ...

  4. ApacheCN 计算机视觉译文集 20210203 更新

    新增了五个教程: OpenCV3 和 Qt5 计算机视觉 零.前言 一.OpenCV 和 Qt 简介 二.创建我们的第一个 Qt 和 OpenCV 项目 三.创建一个全面的 Qt + OpenCV 项 ...

  5. 带你读AI论文:NDSS2020 UNICORN: Runtime Provenance-Based Detector

    摘要:这篇文章将详细介绍NDSS2020的<UNICORN: Runtime Provenance-Based Detector for Advanced Persistent Threats& ...

  6. Spring学习七:ComponentScan注解

    今天主要从以下几个方面来介绍一下@ComponentScan注解: @ComponentScan注解是什么 @ComponentScan注解的详细使用 1.ComponentScan注解是什么 其实很 ...

  7. Android动态加载布局之LayoutInflater【转】

    万分感谢大佬:https://www.jianshu.com/p/6a235ba5ee17 深入了解View<一>之Android LayoutInfalter原理分析 下文为:Layou ...

  8. keystore文件

    [-] keystore操作 运行时签名文件路径debug 生成签名文件打包时使用 获取MD5和SH1 修改keystore文件密码 修改keystore文件别名 修改keystore文件别名的密码 ...

  9. Squid代理服务器应用

    Squid代理服务器应用 目录 Squid代理服务器应用 一.Squid的脚本概念 1. Squid的作用 2. Web代理的工作机制 3. 代理服务器的概念 4. 代理服务器的作用 5. 代理的基本 ...

  10. 【CF457D】Bingo!(数学 期望)

    题目链接 大意 给定\(N,M,K\),表示有一个\(N*N\)的空矩阵,\(M\)个不同的数. 随机地把\(M\)个数中的\(N^2\)个数丢进这个空矩阵中(\(M\ge N^2\)) 再从\(M\ ...