当前位置: 首页 > news >正文

python的WebSocket编程详解,案例群聊系统实现

1.websocket相关

1.1为什么要用websocket

如果有需求要实现服务端向客户端主动推送消息时(比如聊天室,群聊室)有哪几种方案

  • 轮训:让浏览器每隔两秒发送一次请求,缺点:有延时,请求太多网站压力大;
  • 长轮训:客户端向服务端发送请求,服务端最多夯20秒,一旦有新的数据就立即返回断开请求
  • websocket:客户端和服务端创建链接请求不断开,实现双向通道。(推荐)

WebSocket 是一种在 Web 应用程序中实现双向通信的协议。相较于传统的 HTTP 请求-响应模式,WebSocket 提供了全双工的通信方式,使得服务器和客户端之间能够实时地进行双向数据传输。

下面是一些 WebSocket 的应用场景:

  1. 实时聊天:WebSocket 可以用于实时的聊天应用,例如在线客服系统、实时消息推送等。通过 WebSocket 协议,可以实现高效、低延迟的消息传递,提供更好的用户体验。
  2. 多人协作:WebSocket 可以用于多人协作应用,例如实时的协同编辑器、白板工具等。多个用户可以同时编辑共享的文档或画布,实时地看到其他用户的修改。
  3. 实时数据展示:WebSocket 可以用于实时监控和数据展示应用,例如股票行情图、实时天气预报等。通过 WebSocket,可以实时地获取最新的数据,并将其实时展示给用户。
  4. 游戏开发:WebSocket 在游戏开发中也发挥着重要作用。它可以用于实时的游戏对战、多人游戏中的实时交互等。通过 WebSocket,可以实现游戏中玩家之间的实时通信和数据传输。
  5. 远程监控:WebSocket 可以用于远程监控和控制应用,例如远程桌面、远程设备管理等。通过 WebSocket,可以实现实时的屏幕共享、远程操作等功能。

我基于websocket+Django写了一个简单的群聊系统。有感兴趣的同学可以参考我下面提供的源码进行学习,有不懂的,欢迎各位打扰!

下载链接:https://pan.baidu.com/s/1wLhkcRV-3awFz9XMxfWegQ?pwd=yyds
提取码:yyds

1.2websocket介绍

websocket 就是web版的socket

原来的Web中:

  • http协议,无状态,短链接

    • 需要客户端主动链接服务器
    • 客户端再向服务端发送消息,服务端接收消息在响应返回数据
    • 客户端收到数据
    • 断开请求链接
  • https协议,是http+对数据进行加密

我们在开发过程中想要保留一些状态信息,基于Cookie来做

现在web支持:

  • http/https协议,一次请求一次响应
  • websocket协议,创建持久的连接请求不断开,基于这个连接可以进行收发数据,用于【服务端向客户端主动推送消息】
    • web聊天室
    • 实时的图表,柱状图,饼图,投票。
1.3websocket原理
  • http协议

    • 连接
    • 数据传输
    • 断开链接
  • websocket协议,是建立在http协议之上

    • 连接,客户端发起

    • 握手(验证),客户端发送一个消息,服务端收到消息做一些特殊处理并返回。服务器端支持websocket协议。

      • 客户端向服务端发送

        GET /chatsocket HTTP/1.1
        Host:127.0.0.1:8002
        Connection:Upgrade
        Pragma:no-cache
        Cache-Control:no-cache
        Upgrade:websocket
        Origin:http://localhost:63342
        Sec-WebSocket-Version:13
        Sec-WebSocket-Key:mnwFxiOlctXFN/DeMt1Amg==
        Sec-WebSocket-Extensions:permessage-deflate;client_max_window_bits
        ...
        ...
      • 服务器接收(重要)*

      Sec-WebSocket-Key:mnwFxiOlctXFN/DeMt1Amg==与 magic string 进行拼接
      magic string = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
      v1 = "mnwFxiOlctXFN/DeMt1Amg==" + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
      v2 = hmacl(v1)加密1
      v3 = base64(v2)加密2
      
      • 如果服务端匹配成功返回客户端

        HTTP/1.1 101 Switching protocols
        Upgrade:websocket
        Connection:Upgrade
        Sec-WebSocket-Accept:密文(v3)
        
    • 收到数据(加密)

      dfanfsdfmkdsgg;fnfsnfonaoiasdono;fsofnoskfaj
      
      • 先获取两个字节8位。例如10001010

      • 再获取第二个字节的后7位。例如0001010 ——》payload lens

        • =127 ,两个字节8位, 其他字节(4字节masking key + 用户数据)
        • =126 ,两个字节, 其他字节(4字节masking key + 用户数据)
        • <=125 ,两个字节8位, 其他字节(4字节masking key + 用户数据)
      • 获取masking Key 然后对数据进行解密

        var DECODED = " ";
        for(var i = 0;i < DECODED.length;i++){
        DECODED[i]= ENCODED[i]^ MASK[i%4];
        }
        
    • 断开连接

      1.4Django + WebSocket
  • 安装websocket 第三方包

    Django默认不支持websocket,需要安装组件

     pip3 install channels
    
  • 配置

    • 注册channels

      INSTALLED_APPS = ['django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles','channels'
      ]
      • 在setting.py中添加asgi_application

        ASGI_APPLICATION = "websocket.asgi.application"
        
      • 在asgi.py文件中修改

        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', 'websocketp.settings')# application = get_asgi_application()
        application = ProtocolTypeRouter({"http": get_asgi_application(),"websocket": URLRouter(routing.websocket_urlpatterns),
        })
        
      • 在setting同级目录下创建websocket_urls.py

        from django.urls import re_path
        from app01 import websocket_viewswebsocket_urlpatterns = [re_path()
        ]
        
      • 在app01目录下创建websocket_views.py,编写处理websocket的业务逻辑

        from channels.generic.websocket import WebsocketConsumer
        from channels.exceptions import StopConsumerclass ChatConsumer(WebsocketConsumer):def websocket_connect(self, message):# 有客户端来向服务端发送websocket连接的请求时,自动触发# 服务端允许和客户端创建连接self.accept()def websocket_receive(self, message):# 浏览器基于websocket向服务端发送数据,自动触发接收客户端消息print(message)self.send("你好呀你好")self.close()  #表示服务器端主动断开连接def websocket_disconnect(self, message):# 客户端与服务器断开连接时,自动触发print("断开连接")raise StopConsumer()
        
    • 在Django中:

      • WSGI:在以前的学习Django,都是用WSGI
      • ASGI:WSGI+异步编程+websocket
1.5聊天室
  • 访问地址看到聊天室的页面,http请求

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

    • 客户端,websocket。

      socket = new WebSocket("ws://localhost:8000/room/123/");     		
      
    • 服务端 握手并连接成功

      from channels.generic.websocket import WebsocketConsumer
      from channels.exceptions import StopConsumerclass ChatConsumer(WebsocketConsumer):def websocket_connect(self, message):print("有人来连接了....")# 有客户端来向服务端发送websocket连接的请求时,自动触发# 服务端允许和客户端创建连接(握手)self.accept()
      
    • 收发消息

    • 收发消息(客户端的向服务端发消息)

      • 客户端

            <div><input type="text" placeholder="请输入" id="txt"><input type="button" value="发送" onclick="sendMessage()"></div><script>socket = new WebSocket("ws://localhost:8000/room/123/");function sendMessage(){let tag = document.getElementById("txt");socket.send(tag.value);}</script>
        
      • 服务端

        from channels.generic.websocket import WebsocketConsumer
        from channels.exceptions import StopConsumerclass ChatConsumer(WebsocketConsumer):def websocket_connect(self, message):print("有人来连接了....")# 有客户端来向服务端发送websocket连接的请求时,自动触发# 服务端允许和客户端创建连接(握手)self.accept()def websocket_receive(self, message):# 浏览器基于websocket向服务端发送数据,自动触发接收客户端消息print("接收到消息了",message)
        
  • 收发消息(服务端给客户端发消息)

    • 服务端

      from channels.generic.websocket import WebsocketConsumer
      from channels.exceptions import StopConsumerclass ChatConsumer(WebsocketConsumer):def websocket_connect(self, message):print("有人来连接了....")# 有客户端来向服务端发送websocket连接的请求时,自动触发# 服务端允许和客户端创建连接(握手)self.accept()# 服务端给客户端发消息self.send("来了呀客官")         ### 服务端给客户端发消息
      
    • 客户端

      <script>socket = new WebSocket("ws://localhost:8000/room/123/");socket.onmessage = function (event){console.log(event.data)}
      
      • 回调函数 onmessage :当websocket接收到服务端发来的消息时,自动会触发这个函数

        socket.onmessage = function (event){}

      • 回调函数onopen : 当创建好连接之后会自动触发,服务端执行self.accept()之后

        socket.onopen = function (event){}

      • 服务端主动断开连接时,这个方法会被自动触发

      • socket.onclose = function (event){}

      • <script>socket = new WebSocket("ws://localhost:8000/room/123/");// 当创建好连接之后会自动触发,服务端执行self.accept()之后socket.onopen = function (event){let tag = document.createElement("div");tag.innerText = "[连接成功]";document.getElementById("message").appendChild(tag);}// 当websocket接收到服务端发来的消息时,自动会触发这个函数socket.onmessage = function (event){let tag = document.createElement("div");tag.innerText = event.data;document.getElementById("message").appendChild(tag);}// 服务端主动断开连接时,这个方法会被自动触发socket.onclose = function (event){let tag = document.createElement("div");tag.innerText = "[断开连接]";document.getElementById("message").appendChild(tag);}function sendMessage(){let tag = document.getElementById("txt");socket.send(tag.value);}function closeConn(){socket.close();// 向服务端发送断开连接的请求}</script>
        
1.6 群聊1
  • 群聊的简单实现

    from channels.generic.websocket import WebsocketConsumer
    from channels.exceptions import StopConsumerCONN_LIST = []
    class ChatConsumer(WebsocketConsumer):def websocket_connect(self, message):print("有人来连接了....")# 有客户端来向服务端发送websocket连接的请求时,自动触发# 服务端允许和客户端创建连接(握手)self.accept()CONN_LIST.append(self)# 服务端给客户端发消息# self.send("来了呀客官")def websocket_receive(self, message):# 浏览器基于websocket向服务端发送数据,自动触发接收客户端消息print("接收到消息了",message)text = message['text']print("收到消息", text)# if text == '关闭':#     # 想要服务端断开连接, 会给客户端发送断开连接的消息#     self.close()#     returnres = '{}SB'.format(text)for conn in CONN_LIST:conn.send(res)# self.send(res)# self.close()  #表示服务器端主动断开连接# 不管是客户端还是服务端要主动断开时都会执行这个方法def websocket_disconnect(self, message):# 客户端与服务器断开连接时,自动触发print("断开连接")CONN_LIST.remove(self)raise StopConsumer() # 服务端允许客户端断开连接
    
1.7 群聊2

基于channels中提供的channels layers 来实现,需要做以下配置

  • setting中配置。

    方法一:将多个人的连接存储在当前服务器下的内存中

    # 相当于我们自定义的 consumers.py下定义的CONN_LIST = [],意思是 将多个人的连接存储在当前服务器下的内存中   也可以将多个人的连接放在使用redis
    CHANNEL_LAYERS = {"default": {"BACKEND": "channels.layers.InMemoryChannelLayer"}
    }

    方法二:也可以将多个人的连接放在使用redis

    CHANNEL_LAYERS = {"default": {"BACKEND": "channels_redis.core.RedisChannelLayer","CONFIG": {"hosts": ['ip', 'port']}}
    }
    
  • 实现方法:

    from channels.generic.websocket import WebsocketConsumer
    from channels.exceptions import StopConsumer
    from asgiref.sync import async_to_syncclass ChatConsumer(WebsocketConsumer):def websocket_connect(self, message):# 接收这个客户端的连接self.accept()# 将这个客户端的连接对象加入某个地方  (内存 or redis)# 群号  和别名# 获取群号group = self.scope['url_route']['kwargs'].get("group")async_to_sync(self.channel_layer.group_add)(group, self.channel_name)def websocket_receive(self, message):# 通知组内的所有客户端,执行 xx_oo方法 ,在此方法中自己可以去定义任意的功能group = self.scope['url_route']['kwargs'].get("group")async_to_sync(self.channel_layer.group_send)(group, {"type": "xx.oo", "message": message})def xx_oo(self, event):text = event['message']['text']self.send(text)# 不管是客户端还是服务端要主动断开时都会执行这个方法def websocket_disconnect(self, message):# 客户端与服务器断开连接时,自动触发group = self.scope['url_route']['kwargs'].get("group")async_to_sync(self.channel_layer.group_discard)(group, self.channel_name)raise StopConsumer()  # 服务端允许客户端断开连接
    
1.8 总结
  • websocket是什么?协议
  • django中实现websocket,要用到channels组件
    • 单独连接的(一对一)的收发数据
    • 多对多的(比如说群聊)实现 基于Channels_layers

2.websocket编程的代码实例

在 Python 中,有许多库可以用于实现 WebSocket 功能,其中比较常用的是 websockets 库。以下是使用 websockets 库在 Python 中实现一个简单的 WebSocket 服务器和客户端的示例代码:

WebSocket 服务器端代码:

import asyncio
import websocketsasync def handle_websocket(websocket, path):# 处理 WebSocket 连接while True:message = await websocket.recv()print(f"Received message: {message}")# 这里可以根据收到的消息进行相应的处理逻辑response = f"Server received: {message}"await websocket.send(response)print(f"Sent response: {response}")start_server = websockets.serve(handle_websocket, "localhost", 8765)asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()

WebSocket 客户端代码:

import asyncio
import websocketsasync def connect_websocket():async with websockets.connect("ws://localhost:8765") as websocket:while True:message = input("Enter a message to send: ")await websocket.send(message)print(f"Sent message: {message}")response = await websocket.recv()print(f"Received response: {response}")asyncio.get_event_loop().run_until_complete(connect_websocket())

这个示例实现了一个简单的回显功能,当客户端发送消息给服务器时,服务器会将收到的消息原样返回给客户端。

你可以先运行 WebSocket 服务器端代码,在命令行中执行 python server.py,然后再运行 WebSocket 客户端代码,执行 python client.py。在客户端输入消息后,服务器会收到该消息并返回给客户端,客户端再将接收到的响应消息打印出来。

相关文章:

python的WebSocket编程详解,案例群聊系统实现

1.websocket相关 1.1为什么要用websocket 如果有需求要实现服务端向客户端主动推送消息时&#xff08;比如聊天室&#xff0c;群聊室&#xff09;有哪几种方案 轮训&#xff1a;让浏览器每隔两秒发送一次请求&#xff0c;缺点&#xff1a;有延时&#xff0c;请求太多网站压力…...

flutter学习-day22-使用GestureDetector识别手势事件

文章目录 1. 介绍2. 使用2-1. 单击双击和长按2-2. 拖动和滑动2-3. 缩放 3. 注意点 1. 介绍 在 flutter 中&#xff0c;GestureDetector 是手势识别的组件&#xff0c;可以识别点击、双击、长按、拖动、缩放等手势事件&#xff0c;并且可以与子组件进行交互&#xff0c;构造函数…...

uni-app tabbar组件

锋哥原创的uni-app视频教程&#xff1a; 2023版uniapp从入门到上天视频教程(Java后端无废话版)&#xff0c;火爆更新中..._哔哩哔哩_bilibili2023版uniapp从入门到上天视频教程(Java后端无废话版)&#xff0c;火爆更新中...共计23条视频&#xff0c;包括&#xff1a;第1讲 uni…...

【Midjourney】Midjourney根据prompt提示词生成人物图片

目录 &#x1f347;&#x1f347;Midjourney是什么&#xff1f; &#x1f349;&#x1f349;Midjourney怎么用&#xff1f; &#x1f514;&#x1f514;Midjourney提示词格式 Midjourney生成任务示例 例1——航空客舱与乘客 prompt prompt翻译 生成效果 大图展示 细节大…...

Oracle 拼接字符串

语法 使用||拼接如果内容中有单引号&#xff0c;则可在该单引号前面再加一个单引号进行转义 例子 比如有一个业务是根据需要生成多条插入语句 select insert into des_account_des_role(des_account_id, roles_id) values( || id || , || (select id from des_role where wo…...

探究公有云中的巨人:深入分析大数据产品的架构设计

目录 一、服务器分类 二、公有云基础和产品 网络 vpc专有网络 弹性公网IP(Elastic IP)...

亚马逊云科技 re:Invent 2023 产品体验:亚马逊云科技产品应用实践 王炸产品 Amazon Q,你的 AI 助手

意料之中 2023年9月25日&#xff0c;亚马逊宣布与 Anthropic 正式展开战略合作&#xff0c;结合双方在更安全的生成式 AI 领域的先进技术和专业知识&#xff0c;加速 Anthropic 未来基础模型的开发&#xff0c;并将其广泛提供给亚马逊云科技的客户使用。 亚马逊云科技开发者社…...

并发编程大杀器,京东多线程编排工具asyncTool

一、简介 并发编程大杀器&#xff0c;京东多线程编排工具asyncTool&#xff0c;可以解决任意的多线程并行、串行、阻塞、依赖、回调的并行框架&#xff0c;可以任意组合各线程的执行顺序&#xff0c;带全链路执行结果回调。多线程编排一站式解决方案。 二、特点 多线程编排&am…...

【开源项目】智慧交通~超经典开源项目实景三维数字孪生高速

数字孪生高速运营管理平台&#xff0c;以提升高速公路管理水平和方便出行为主要目标&#xff0c;充分利用云计算、AI、大数据等&#xff0c;实现对高速公路控制、指挥、运营的智能化。飞渡科技以实景三维数据为基础&#xff0c;基于大数据、高分遥感、数据分析以及数据融合等前…...

udp多播/组播那些事

多播与组播 多播&#xff08;multicast&#xff09;和组播&#xff08;groupcast&#xff09;是相同的概念&#xff0c;用于描述在网络中一对多的通信方式。在网络通信中&#xff0c;单播&#xff08;unicast&#xff09;是一对一的通信方式&#xff0c;广播&#xff08;broad…...

C++ Qt开发:SqlRelationalTable关联表组件

Qt 是一个跨平台C图形界面开发库&#xff0c;利用Qt可以快速开发跨平台窗体应用程序&#xff0c;在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置&#xff0c;实现图形化开发极大的方便了开发效率&#xff0c;本章将重点介绍SqlRelationalTable关联表组件的常用方法及灵…...

【LeetCode】修炼之路-0001-Two Sum(两数之和)【python】【简单】

前言 计算机科学作为一门实践性极强的学科,代码能力的培养尤为重要。当前网络上有非常多优秀的前辈分享了LeetCode的最佳算法题解,这对于我们这些初学者来说提供了莫大的帮助,但对于我这种缺乏编程直觉的学习者而言,这往往难以消化吸收。&#xff08;为什么别人就能想出这么优雅…...

秋招复习篇之代码规范

目录 前言 1、变量命名 2、代码空格 1&#xff09;操作符左右一定有空格&#xff0c; 2&#xff09;分隔符&#xff08;, 和;&#xff09;前一位没有空格&#xff0c;后一位保持空格&#xff0c;例如&#xff1a; 3&#xff09;大括号和函数保持同一行&#xff0c;并有一个空格…...

Docker:登录私有仓库\退出私有仓库

一、登录仓库 docker login : 登录到一个Docker镜像仓库&#xff0c;如果未指定镜像仓库地址&#xff0c;默认为官方仓库 Docker Hub 语法: docker login [OPTIONS] [SERVER] docker login -u 用户名 -p 密码 仓库名称 # 登入私有仓库 [rootlocalhost ~]# docker login --…...

与擎创科技共建一体化“数智”运维体系,实现数字化转型

小窗滴滴小编获取最新版公司简介 前言&#xff1a; 哈喽大家好&#xff0c;最近分享的互联网IT热讯大家都挺喜欢&#xff0c;小编看着数据着实开心&#xff0c;感谢大家支持&#xff0c;小编会继续给大家推送。 新岁即将启封&#xff0c;我们一年一期的运维干货年末大讲也要…...

开放网络+私有云=?星融元的私有云承载网络解决方案实例

在全世界范围内的云服务市场上&#xff0c;开放网络一直是一个备受关注的话题。相比于传统供应商的网络设备&#xff0c;开放网络具备软硬件解耦、云原生、可选组件丰富等优势&#xff0c;对云服务商和超大型企业有足够的吸引力。 SONiC作为开源的网络操作系统&#xff0c;使得…...

【Linux学习笔记】Linux下nginx环境搭建

1、下载nginx 安装rpm命令: rpm ivh nginx-release.rpm。(直接使用linux命令下载wget http://nginx.org/packages/rhel/6/noarch/RPMS/nginx-release-rhel-6-0.el6.ngx.noarch.rpm 2、设置nginx开机启动 chkconfig nginx on 3、开启nginx服务 方法一&#xff1a;service nginx…...

Python打包

将 Python 脚本打包成可执行的 .exe 文件,通常可以使用 PyInstaller 这个库来实现。PyInstaller 是一个流行的工具,它可以将 Python 程序和所有相关的依赖打包成一个独立的可执行文件,适用于 Windows、Linux 和 macOS 系统。安装 PyInstaller 首先,需要安装 PyInstaller。…...

2023启示录丨自动驾驶这一年

图片&#xff5c;《老人与海》插图 过去的20年&#xff0c;都没有2023年如此动荡。 大模型犹如一颗原子弹投入科技圈&#xff0c;卷起万里尘沙&#xff0c;传统模式瞬间被夷为平地&#xff0c;在耀眼的白光和巨大的轰鸣声之下&#xff0c;大公司、创业者、投资人甚至是每一位观…...

node实现对git仓库的管理

一、项目背景 一份代码&#xff0c;发布多个小程序。想让技术支持部通过脚本自己获取代码&#xff0c;并通过脚本自动提交到客户的小程序后台。他们自行发布。 现已注册第三方平台&#xff0c;开发人员通过“开发小程序”上传模板。开发人员把代码上传到模板&#xff0c;支持…...

大数据学习栈记——Neo4j的安装与使用

本文介绍图数据库Neofj的安装与使用&#xff0c;操作系统&#xff1a;Ubuntu24.04&#xff0c;Neofj版本&#xff1a;2025.04.0。 Apt安装 Neofj可以进行官网安装&#xff1a;Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...

HTML 语义化

目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案&#xff1a; 语义化标签&#xff1a; <header>&#xff1a;页头<nav>&#xff1a;导航<main>&#xff1a;主要内容<article>&#x…...

C++_核心编程_多态案例二-制作饮品

#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为&#xff1a;煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例&#xff0c;提供抽象制作饮品基类&#xff0c;提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...

Spark 之 入门讲解详细版(1)

1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室&#xff08;Algorithms, Machines, and People Lab&#xff09;开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目&#xff0c;8个月后成为Apache顶级项目&#xff0c;速度之快足见过人之处&…...

阿里云ACP云计算备考笔记 (5)——弹性伸缩

目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...

相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解

【关注我&#xff0c;后续持续新增专题博文&#xff0c;谢谢&#xff01;&#xff01;&#xff01;】 上一篇我们讲了&#xff1a; 这一篇我们开始讲&#xff1a; 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下&#xff1a; 一、场景操作步骤 操作步…...

Mac软件卸载指南,简单易懂!

刚和Adobe分手&#xff0c;它却总在Library里给你写"回忆录"&#xff1f;卸载的Final Cut Pro像电子幽灵般阴魂不散&#xff1f;总是会有残留文件&#xff0c;别慌&#xff01;这份Mac软件卸载指南&#xff0c;将用最硬核的方式教你"数字分手术"&#xff0…...

从零实现STL哈希容器:unordered_map/unordered_set封装详解

本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说&#xff0c;直接开始吧&#xff01; 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...

浪潮交换机配置track检测实现高速公路收费网络主备切换NQA

浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求&#xff0c;本次涉及的主要是收费汇聚交换机的配置&#xff0c;浪潮网络设备在高速项目很少&#xff0c;通…...

08. C#入门系列【类的基本概念】:开启编程世界的奇妙冒险

C#入门系列【类的基本概念】&#xff1a;开启编程世界的奇妙冒险 嘿&#xff0c;各位编程小白探险家&#xff01;欢迎来到 C# 的奇幻大陆&#xff01;今天咱们要深入探索这片大陆上至关重要的 “建筑”—— 类&#xff01;别害怕&#xff0c;跟着我&#xff0c;保准让你轻松搞…...