C#使用MQTT(一):MQTT服务端
MQTT(Message Queuing Telemetry Transport)
即时通讯协议,
开发商 IBM
MQTT(消息队列遥测传输)是ISO 标准(ISO/IEC PRF 20922)下基于发布/订阅范式的消息协议。它工作在 TCP/IP协议族上,是为硬件性能低下的远程设备以及网络状况糟糕的情况下而设计的发布/订阅型消息协议,为此,它需要一个消息中间件 。
MQTT是一个基于客户端-服务器的消息发布/订阅传输协议。MQTT协议是轻量、简单、开放和易于实现的,这些特点使它适用范围非常广泛。在很多情况下,包括受限的环境中,如:机器与机器(M2M)通信和物联网(IoT)。其在,通过卫星链路通信传感器、偶尔拨号的医疗设备、智能家居、及一些小型化设备中已广泛使用。
新建Winform应用程序,将默认的Form1重命名为FormMqttServer
管理Nuget包,输入关键字Mqtt
点击安装
安装完成后示例如图
我们使用MQTTnet.dll,程序集 MQTTnet, Version=4.3.6.1152。应用程序.net framework版本需要4.6.1或者以上
窗体 FormMqttServer 设计如下:
窗体 FormMqttServer设计器代码如下:
文件 FormMqttServer.Designer.cs
namespace CultureDemo
{partial class FormMqttServer{/// <summary>/// Required designer variable./// </summary>private System.ComponentModel.IContainer components = null;/// <summary>/// Clean up any resources being used./// </summary>/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>protected override void Dispose(bool disposing){if (disposing && (components != null)){components.Dispose();}base.Dispose(disposing);}#region Windows Form Designer generated code/// <summary>/// Required method for Designer support - do not modify/// the contents of this method with the code editor./// </summary>private void InitializeComponent(){this.lvTopic = new System.Windows.Forms.ListBox();this.lbClients = new System.Windows.Forms.ListBox();this.rtxtMessage = new System.Windows.Forms.RichTextBox();this.label5 = new System.Windows.Forms.Label();this.label4 = new System.Windows.Forms.Label();this.btnStop = new System.Windows.Forms.Button();this.btnStart = new System.Windows.Forms.Button();this.txtPassword = new System.Windows.Forms.TextBox();this.label3 = new System.Windows.Forms.Label();this.txtUsername = new System.Windows.Forms.TextBox();this.label2 = new System.Windows.Forms.Label();this.txtPort = new System.Windows.Forms.TextBox();this.label1 = new System.Windows.Forms.Label();this.txtIP = new System.Windows.Forms.TextBox();this.lb = new System.Windows.Forms.Label();this.dgvTopic = new System.Windows.Forms.DataGridView();this.Column1 = new System.Windows.Forms.DataGridViewTextBoxColumn();this.Column2 = new System.Windows.Forms.DataGridViewTextBoxColumn();this.Column3 = new System.Windows.Forms.DataGridViewTextBoxColumn();this.Column4 = new System.Windows.Forms.DataGridViewTextBoxColumn();((System.ComponentModel.ISupportInitialize)(this.dgvTopic)).BeginInit();this.SuspendLayout();// // lvTopic// this.lvTopic.FormattingEnabled = true;this.lvTopic.ItemHeight = 12;this.lvTopic.Location = new System.Drawing.Point(686, 35);this.lvTopic.Name = "lvTopic";this.lvTopic.Size = new System.Drawing.Size(300, 136);this.lvTopic.TabIndex = 31;// // lbClients// this.lbClients.FormattingEnabled = true;this.lbClients.ItemHeight = 12;this.lbClients.Location = new System.Drawing.Point(343, 35);this.lbClients.Name = "lbClients";this.lbClients.Size = new System.Drawing.Size(300, 136);this.lbClients.TabIndex = 30;// // rtxtMessage// this.rtxtMessage.Location = new System.Drawing.Point(24, 188);this.rtxtMessage.Name = "rtxtMessage";this.rtxtMessage.Size = new System.Drawing.Size(467, 338);this.rtxtMessage.TabIndex = 29;this.rtxtMessage.Text = "";// // label5// this.label5.AutoSize = true;this.label5.Location = new System.Drawing.Point(684, 17);this.label5.Name = "label5";this.label5.Size = new System.Drawing.Size(53, 12);this.label5.TabIndex = 28;this.label5.Text = "主题列表";// // label4// this.label4.AutoSize = true;this.label4.Location = new System.Drawing.Point(341, 17);this.label4.Name = "label4";this.label4.Size = new System.Drawing.Size(65, 12);this.label4.TabIndex = 27;this.label4.Text = "连接客户端";// // btnStop// this.btnStop.Location = new System.Drawing.Point(129, 148);this.btnStop.Name = "btnStop";this.btnStop.Size = new System.Drawing.Size(75, 23);this.btnStop.TabIndex = 26;this.btnStop.Text = "停止";this.btnStop.UseVisualStyleBackColor = true;this.btnStop.Click += new System.EventHandler(this.btnStop_Click);// // btnStart// this.btnStart.Location = new System.Drawing.Point(32, 148);this.btnStart.Name = "btnStart";this.btnStart.Size = new System.Drawing.Size(75, 23);this.btnStart.TabIndex = 25;this.btnStart.Text = "启动";this.btnStart.UseVisualStyleBackColor = true;this.btnStart.Click += new System.EventHandler(this.btnStart_Click);// // txtPassword// this.txtPassword.Location = new System.Drawing.Point(91, 121);this.txtPassword.Name = "txtPassword";this.txtPassword.Size = new System.Drawing.Size(211, 21);this.txtPassword.TabIndex = 24;this.txtPassword.Text = "1";// // label3// this.label3.AutoSize = true;this.label3.Location = new System.Drawing.Point(44, 124);this.label3.Name = "label3";this.label3.Size = new System.Drawing.Size(29, 12);this.label3.TabIndex = 23;this.label3.Text = "密码";// // txtUsername// this.txtUsername.Location = new System.Drawing.Point(91, 94);this.txtUsername.Name = "txtUsername";this.txtUsername.Size = new System.Drawing.Size(211, 21);this.txtUsername.TabIndex = 22;this.txtUsername.Text = "a";// // label2// this.label2.AutoSize = true;this.label2.Location = new System.Drawing.Point(44, 97);this.label2.Name = "label2";this.label2.Size = new System.Drawing.Size(29, 12);this.label2.TabIndex = 21;this.label2.Text = "账号";// // txtPort// this.txtPort.Location = new System.Drawing.Point(91, 58);this.txtPort.Name = "txtPort";this.txtPort.Size = new System.Drawing.Size(211, 21);this.txtPort.TabIndex = 20;this.txtPort.Text = "12345";// // label1// this.label1.AutoSize = true;this.label1.Location = new System.Drawing.Point(44, 61);this.label1.Name = "label1";this.label1.Size = new System.Drawing.Size(29, 12);this.label1.TabIndex = 19;this.label1.Text = "端口";// // txtIP// this.txtIP.Location = new System.Drawing.Point(91, 16);this.txtIP.Name = "txtIP";this.txtIP.Size = new System.Drawing.Size(211, 21);this.txtIP.TabIndex = 18;this.txtIP.Text = "127.0.0.1";// // lb// this.lb.AutoSize = true;this.lb.Location = new System.Drawing.Point(32, 19);this.lb.Name = "lb";this.lb.Size = new System.Drawing.Size(41, 12);this.lb.TabIndex = 17;this.lb.Text = "IP地址";// // dgvTopic// this.dgvTopic.AllowUserToAddRows = false;this.dgvTopic.AllowUserToDeleteRows = false;this.dgvTopic.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;this.dgvTopic.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {this.Column1,this.Column2,this.Column3,this.Column4});this.dgvTopic.Location = new System.Drawing.Point(522, 188);this.dgvTopic.Name = "dgvTopic";this.dgvTopic.ReadOnly = true;this.dgvTopic.RowTemplate.Height = 23;this.dgvTopic.Size = new System.Drawing.Size(464, 338);this.dgvTopic.TabIndex = 32;// // Column1// this.Column1.HeaderText = "Topic";this.Column1.Name = "Column1";this.Column1.ReadOnly = true;// // Column2// this.Column2.HeaderText = "ClientId";this.Column2.Name = "Column2";this.Column2.ReadOnly = true;// // Column3// this.Column3.HeaderText = "Qos";this.Column3.Name = "Column3";this.Column3.ReadOnly = true;// // Column4// this.Column4.HeaderText = "SessionItems";this.Column4.Name = "Column4";this.Column4.ReadOnly = true;// // FormMqttServer// this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;this.ClientSize = new System.Drawing.Size(1013, 538);this.Controls.Add(this.dgvTopic);this.Controls.Add(this.lvTopic);this.Controls.Add(this.lbClients);this.Controls.Add(this.rtxtMessage);this.Controls.Add(this.label5);this.Controls.Add(this.label4);this.Controls.Add(this.btnStop);this.Controls.Add(this.btnStart);this.Controls.Add(this.txtPassword);this.Controls.Add(this.label3);this.Controls.Add(this.txtUsername);this.Controls.Add(this.label2);this.Controls.Add(this.txtPort);this.Controls.Add(this.label1);this.Controls.Add(this.txtIP);this.Controls.Add(this.lb);this.Name = "FormMqttServer";this.Text = "FormMqttServer";this.Load += new System.EventHandler(this.FormMqttServer_Load);((System.ComponentModel.ISupportInitialize)(this.dgvTopic)).EndInit();this.ResumeLayout(false);this.PerformLayout();}#endregionprivate System.Windows.Forms.ListBox lvTopic;private System.Windows.Forms.ListBox lbClients;private System.Windows.Forms.RichTextBox rtxtMessage;private System.Windows.Forms.Label label5;private System.Windows.Forms.Label label4;private System.Windows.Forms.Button btnStop;private System.Windows.Forms.Button btnStart;private System.Windows.Forms.TextBox txtPassword;private System.Windows.Forms.Label label3;private System.Windows.Forms.TextBox txtUsername;private System.Windows.Forms.Label label2;private System.Windows.Forms.TextBox txtPort;private System.Windows.Forms.Label label1;private System.Windows.Forms.TextBox txtIP;private System.Windows.Forms.Label lb;private System.Windows.Forms.DataGridView dgvTopic;private System.Windows.Forms.DataGridViewTextBoxColumn Column1;private System.Windows.Forms.DataGridViewTextBoxColumn Column2;private System.Windows.Forms.DataGridViewTextBoxColumn Column3;private System.Windows.Forms.DataGridViewTextBoxColumn Column4;}
}
窗体FormMqttServer代码如下【MQTT服务端相关代码】
文件FormMqttServer.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;using MQTTnet.Server;
using MQTTnet;
using MQTTnet.Protocol;
using System.Collections;namespace CultureDemo
{public partial class FormMqttServer : Form{private MqttServer server;//mqtt服务器对象public FormMqttServer(){InitializeComponent();rtxtMessage.ReadOnly = true;/** 在MQTT协议中,一个MQTT数据包由:固定头(Fixed header)、可变头(Variable header)、消息体(payload)三部分构成。
固定头(Fixed header):存在于所有MQTT数据包中,表示数据包类型及数据包的分组类标识。
可变头(Variable header):存在于部分MQTT数据包中,数据包类型决定了可变头是否存在及其具体内容。
消息体(Payload):存在于部分MQTT数据包中,表示客户端收到的具体内容。*/}/// <summary>/// 打印相关消息/// </summary>/// <param name="contents"></param>private void DisplayMessage(string contents) {if (!this.IsHandleCreated) {return;}this.BeginInvoke(new Action(() => {if (rtxtMessage.TextLength >= 40960) {rtxtMessage.Clear();}rtxtMessage.AppendText($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}->{contents}\n");rtxtMessage.ScrollToCaret();}));}/// <summary>/// 初始化Mqtt服务并启动服务/// </summary>/// <param name="ip">IPV4地址</param>/// <param name="port">端口:0~65535之间</param>private Task StartMqttServer(string ip, int port){MqttServerOptions mqttServerOptions =new MqttServerOptionsBuilder().WithDefaultEndpoint().WithDefaultEndpointBoundIPAddress(System.Net.IPAddress.Parse(ip)).WithDefaultEndpointPort(port) .WithDefaultCommunicationTimeout(TimeSpan.FromMilliseconds(5000)).Build();server = new MqttFactory().CreateMqttServer(mqttServerOptions); // create MQTT service objectserver.ValidatingConnectionAsync += Server_ValidatingConnectionAsync;//验证用户名和密码server.ClientConnectedAsync += Server_ClientConnectedAsync;//绑定客户端连接事件server.ClientDisconnectedAsync += Server_ClientDisconnectedAsync;//绑定客户端断开事件server.ClientSubscribedTopicAsync += Server_ClientSubscribedTopicAsync;//绑定客户端订阅主题事件server.ClientUnsubscribedTopicAsync += Server_ClientUnsubscribedTopicAsync;//绑定客户端退订主题事件server.InterceptingPublishAsync += Server_InterceptingPublishAsync;//消息接收事件server.ClientAcknowledgedPublishPacketAsync += Server_ClientAcknowledgedPublishPacketAsync;server.InterceptingClientEnqueueAsync += Server_InterceptingClientEnqueueAsync;server.ApplicationMessageNotConsumedAsync += Server_ApplicationMessageNotConsumedAsync;server.StartedAsync += Server_StartedAsync;//绑定服务端启动事件server.StoppedAsync += Server_StoppedAsync;//绑定服务端停止事件return server.StartAsync();}private Task Server_ApplicationMessageNotConsumedAsync(ApplicationMessageNotConsumedEventArgs e){try{DisplayMessage($"【MessageNotConsumed】-SenderId:{e.SenderId}-Message:{e.ApplicationMessage.ConvertPayloadToString()}");}catch (Exception ex){DisplayMessage($"Server_ApplicationMessageNotConsumedAsync出现异常:{ex.Message}");}return Task.CompletedTask;}private Task Server_InterceptingClientEnqueueAsync(InterceptingClientApplicationMessageEnqueueEventArgs e){try{DisplayMessage($"【InterceptingClientEnqueue】-SenderId:{e.SenderClientId}-Message:{e.ApplicationMessage.ConvertPayloadToString()}");}catch (Exception ex){DisplayMessage($"Server_InterceptingClientEnqueueAsync出现异常:{ex.Message}");}return Task.CompletedTask;}private Task Server_ClientAcknowledgedPublishPacketAsync(ClientAcknowledgedPublishPacketEventArgs e){try{DisplayMessage($"【ClientAcknowledgedPublishPacket】-SenderId:{e.ClientId}-Message:{Encoding.UTF8.GetString(e.PublishPacket.PayloadSegment.ToArray())}");}catch (Exception ex){DisplayMessage($"Server_ClientAcknowledgedPublishPacketAsync出现异常:{ex.Message}");}return Task.CompletedTask;}/// <summary>/// 消息接收/// </summary>/// <param name="arg"></param>/// <returns></returns>private Task Server_InterceptingPublishAsync(InterceptingPublishEventArgs e){try{string client = e.ClientId;string topic = e.ApplicationMessage.Topic;string contents = e.ApplicationMessage.ConvertPayloadToString();//Encoding.UTF8.GetString(arg.ApplicationMessage.PayloadSegment.ToArray());DisplayMessage($"接收到消息:Client:【{client}】 Topic:【{topic}】 Message:【{contents}】");}catch (Exception ex){DisplayMessage($"Server_InterceptingPublishAsync出现异常:{ex.Message}");}return Task.CompletedTask;}private void FormMqttServer_Load(object sender, EventArgs e){rtxtMessage.Text = @"MQTT服务端关键事件说明:
ClientConnectedAsync-->绑定客户端连接事件
ValidatingConnectionAsync-->验证用户名和密码
ClientSubscribedTopicAsync-->绑定客户端订阅主题事件
InterceptingPublishAsync-->消息接收事件
";}private Task Server_StoppedAsync(EventArgs arg){return Task.Run(new Action(() =>{DisplayMessage($"服务端【{txtIP.Text}:{txtPort.Text}】已停止MQTT");}));}private Task Server_StartedAsync(EventArgs e){return Task.Run(new Action(() =>{DisplayMessage($"服务端【{txtIP.Text}:{txtPort.Text}】已启用MQTT");}));}private Task Server_ClientUnsubscribedTopicAsync(ClientUnsubscribedTopicEventArgs e){return Task.Run(new Action(() =>{lvTopic.Invoke(new Action(() =>{string itemContents = $"【{e.ClientId}】订阅主题【{e.TopicFilter}】";if (lvTopic.Items.Contains(itemContents)){//如果存在该项,就移除lvTopic.Items.Remove(itemContents);}IDictionary collection = e.SessionItems;string[] sessionItemContents = new string[collection.Count];int idx = 0;foreach (object key in collection.Keys){sessionItemContents[idx++] = $"[{key}:{collection[key]}]";}}));DisplayMessage($"客户端【{e.ClientId}】退订主题【{e.TopicFilter}】");}));}private Task Server_ClientSubscribedTopicAsync(ClientSubscribedTopicEventArgs e){return Task.Run(new Action(() =>{lvTopic.Invoke(new Action(() =>{string itemContents = $"【{e.ClientId}】订阅主题【{e.TopicFilter.Topic}】";if (!lvTopic.Items.Contains(itemContents)){//如果不存在该项,就添加lvTopic.Items.Add(itemContents);}IDictionary collection = e.SessionItems;string[] sessionItemContents = new string[collection.Count];int idx = 0;foreach (object key in collection.Keys){sessionItemContents[idx++] = $"[{key}:{collection[key]}]";}dgvTopic.Rows.Add(e.TopicFilter.Topic, e.ClientId, e.TopicFilter.QualityOfServiceLevel, string.Join(",", sessionItemContents));}));DisplayMessage($"客户端【{e.ClientId}】订阅主题【{e.TopicFilter.Topic}】");}));}private Task Server_ClientDisconnectedAsync(ClientDisconnectedEventArgs e){return Task.Run(new Action(() =>{lbClients.BeginInvoke(new Action(() =>{lbClients.Items.Remove(e.ClientId);}));DisplayMessage($"客户端已断开.ClientId:【{e.ClientId}】,Endpoint:【{e.Endpoint}】.ReasonCode:【{e.ReasonCode}】,DisconnectType:【{e.DisconnectType}】");}));}/// <summary>/// 绑定客户端连接事件/// </summary>/// <param name="arg"></param>/// <returns></returns>private Task Server_ClientConnectedAsync(ClientConnectedEventArgs e){return Task.Run(new Action(() =>{lbClients.BeginInvoke(new Action(() =>{lbClients.Items.Add(e.ClientId);}));DisplayMessage($"客户端已连接.ClientId:【{e.ClientId}】,Endpoint:【{e.Endpoint}】");}));}private Task Server_ValidatingConnectionAsync(ValidatingConnectionEventArgs e){return Task.Run(new Action(() =>{string UserName = txtUsername.Text;string Password = txtPassword.Text;if (e.UserName == UserName && e.Password == Password){e.ReasonCode = MqttConnectReasonCode.Success;DisplayMessage($"客户端已验证成功.ClientId:【{e.ClientId}】,Endpoint:【{e.Endpoint}】");}else{e.ReasonCode = MqttConnectReasonCode.BadUserNameOrPassword;DisplayMessage($"客户端验证失败.ClientId:【{e.ClientId}】,Endpoint:【{e.Endpoint}】");}}));}private async void btnStart_Click(object sender, EventArgs e){await StartMqttServer(txtIP.Text, int.Parse(txtPort.Text));btnStart.Enabled = false;}private async void btnStop_Click(object sender, EventArgs e){await server.StopAsync();btnStart.Enabled = true;}}
}
程序运行如图:
连接、订阅、发布消息如图
相关文章:

C#使用MQTT(一):MQTT服务端
MQTT(Message Queuing Telemetry Transport) 即时通讯协议, 开发商 IBM MQTT(消息队列遥测传输)是ISO 标准(ISO/IEC PRF 20922)下基于发布/订阅范式的消息协议。它工作在 TCP/IP协议族上,是为硬件性能低下的远程设备以及网络状…...

AD原理图update为pcb
首先,要在自己的项目下面创建好原理图和PCB,记得保存!!! 点击设计>update 更新成功!...

应用海外仓系统后,可以改善哪些海外仓的核心业务流程?
随着跨境电商的快速发展,海外仓作为物流的重要环节,其运营效率直接影响到企业的市场竞争力。应用海外仓系统(WMS)可以有效改善海外仓的核心业务流程,以下将详细介绍四大核心流程的优化措施。 一、货物接收入库流程的改…...

SQL进阶技巧:截止当前批次前的批次量与订单量 | 移动窗口问题
目录 0 场景描述 1 数据准备 2 问题分析 3 小结 0 场景描述 表A有如下字段,user id(用户ID),batch id(批次ID),order id(订单ID),create time(创建时间),同一个用户ID下有多个批次,同一个批次下有多个订单ID,相同批次ID的创建时间是相同的,创建时间精确到了秒。 统计,截…...

C#中的Graphics类和SetQuality()自定义方法
在 C# 中,Graphics 类是 System.Drawing 命名空间的一部分,它提供了一组方法和属性,用于在 Windows Forms 应用程序中进行二维绘图。Graphics 对象可以绘制文本、线条、曲线、形状和图像,并可以对它们进行变换和剪辑。 Graphics …...

圣诞节:白酒与西式料理的异国风情
随着冬日的脚步渐近,圣诞的钟声即将敲响。在这个充满异国情调和温馨氛围的节日里,一场中西合璧的美食盛宴悄然上演。豪迈白酒(HOMANLISM)与西式料理的碰撞,不仅为圣诞餐桌增添了几分不同的韵味,更让人们在这…...

2.ChatGPT的发展历程:从GPT-1到GPT-4(2/10)
引言 在人工智能领域,自然语言处理(NLP)是连接人类与机器的重要桥梁。随着技术的不断进步,我们见证了从简单的文本分析到复杂的语言理解的转变。ChatGPT,作为自然语言处理领域的一个里程碑,其发展历程不仅…...

yjs01——机器学习的过程
ps:换了阿婆主重新看机器学习 机器学习的过程: 1.获取数据——2.数据基本处理——>3.特征工程——>4.机器学习(模型训练)—>模型评估 获取数据: 1.专有名词: 1.样本:一行数据是一个样本…...

Git工作流程
git 工作流程 克隆或同步远程仓库 使用git clone命令将本仓库完全镜像一份至本地 使用git pull命令将远程仓库代码同步到本地新建或修改代码文件后,将代码提交到暂存区;(git add filename)将暂存区域的文件提交到本地git仓库。(git commit filename -m …...

Qt-QWidget的font属性(18)
目录 描述 相关API 使用 使用Qt Designer设置字体 使用纯代码设置字体 描述 这个是用来设置字体样式的 相关API 使用 我们创建一个新的项目 使用Qt Designer设置字体 使用纯代码设置字体 相比于上面使用Qt Designer,用代码来实现就要灵活的多,主…...

Go语言概述
1.Go语言的特点 1)从语言层面支持并发,实现简单 2)goroutine,轻量级线程,可实现大并发处理,高效利用多核 3)垃圾回收机制,内存自动回收,不需要开发人员管理 4࿰…...

P6627 [省选联考 2020 B 卷] 幸运数字
*原题链接* 并不是非常难的题,不过细节非常多。 首先大题思路很明确,把所有条件储存下来,把这些l,r,x啥的离散化,然后区间异或,最后查询最大值。至于区间异或用差分就好了,因为异或…...

活动|华院计算宣晓华受邀出席“AI引领新工业革命”大会,探讨全球科技的最新趋势
8月31日,“AI引领新工业革命”大会于上海图书馆圆满落幕。本次大会由TAA校联会和台协科创工委会联合主办,得到上海市台办、上海市台联、康师傅的大力支持。大会邀请了NVIDIA全球副总裁、亚太区企业营销负责人刘念宁,元禾厚望资本创始合伙人潘…...

k8s配置
一、前期准备 1、修改主机的/etc/hosts文件挟持域名 [rootk8s-master ~]# vim /etc/hosts 192.168.8.199 k8s-master 192.168.8.200 k8s-node1 192.168.8.201 k8s-node2 2、配置yum源 [rootk8s-master ~]# cd /etc/yum.repos.d/ [rootk8s-master yum.repos.d]# vim kubernetes…...

力扣第79题 单词搜索
前言 记录一下刷题历程 力扣第79题 单词搜索 单词搜索 原题目:给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。 单词必须按照字母顺序,通过相邻…...

【系统架构设计师】抽象工厂设计模式
抽象工厂(Abstract Factory)模式是一种创建型设计模式,它提供了一种创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。在抽象工厂模式中,客户端不依赖于产品类实例的如何被创建、组合和表达的细节,这对于产品族(即一组相互关联或相互依赖的产品)的创建尤其…...

海外云手机有哪些推荐?
随着云手机的发展,越来越多的企业和个人开始使用云手机来满足他们的海外业务需求。用户可以通过云手机实现方便、快捷的海外访问,一般用来进行tiktok运营、亚马逊电商运营、海外社媒运营等操作。海外云手机平台有很多,以下是一些比较好的云手…...

旋转目标检测对照实验-mmrotate基础教程
环境安装和测试可以参考mmrotate旋转目标检测实战指南_validate mmrotate-CSDN博客 使用自定义数据集训练 如果需要使用自己的数据集进行训练,首先需要把自己数据的标签格式转换为dota数据集的格式,形如(前八个数为坐标值,第九个…...

Spring常见的面试问答题(一)
在面试过程中,Spring几乎是必问的几个点之一,特别是其中的IOC和AOP。 Spring常见的面试问答题 什么是Spring? 首先,Spring是一个生态,但是呢,这个生态里面又有个Spring Framework框架。 所以从Spring生…...

STM32 之 SDRAM 详解
目录 前言 一、SDRAM 简介 二、SDRAM的组成原理 2.1存储单元阵列 2.1.1地址译码 2.1.2存储电容 2.2控制逻辑 2.2.1时钟同步 2.2.2命令解码 2.2.3模式寄存器 2.3数据输入 / 输出缓冲 2.3.1数据总线 2.3.2数据锁存 2.4刷新电路 2.4.1自动刷新 2.4.2自刷新 三、S…...

基于图神经网络的最大独立集问题的目标分支
文章目录 Abstract1 Introduction2 Related Work分支顶点选择图神经网络Abstract 分支归约方法结合了分支约束原则和归约规则,在处理以前无法管理的现实世界实例方面特别成功。分支策略决定下一个要在哪个顶点上进行分支。最近,最广泛使用的策略是选择最高度的顶点。 在这项…...

【Qt】事件过滤器
事件过滤器 在 Qt 中,⼀个对象可能经常要查看或拦截另外⼀个对象的事件,如对话框想要拦截按键事件,不让别的组件接收到,或者修改按键的默认值等。通过上⾯的学习,我们已经知道,Qt 创建了 QEvent事件对象之后…...

字符串转换为整数、整数转换为字符串
整数转换为字符串 sprintf()它的功能是将各种类型的数据格式化为字符串,并存储到一个字符数组中。 sprintf 是 C 语言标准库中的一个函数,用于将格式化的数据写入一个字符串中。它的用法与 printf 类似,但不同的是,printf 输出到…...

解决samba无权限创建文件问题
将我服务器利用samba工具映射到到电脑后,没有权限在特定的文件里写文件,比如在mcu这个文件夹里面没有写文件的权限。 查看mcu文件夹的用户属性,属于root属性。 rootzwzn2064-CVN-Z690D5-GAMING-PRO:/home/zwzn2064# ls -ll total 9714860 dr…...

Ribbon快速了解
Ribbon 一、Ribbon 介绍 Ribbon 是一个客户端负载均衡器,它是 Netflix 开源的一个组件,常与 Spring Cloud 一起使用。 二、Ribbon 的作用 客户端负载均衡 Ribbon 可以在客户端实现负载均衡,即在服务消费者端根据一定的算法从多个服务提供者实…...

SpringBoot闲一品交易平台
SpringBoot闲一品交易平台 #vue项目实战 #计算机项目 #java项目 SpringBoot闲一品交易平台通过运用软件工程原理和开发方法,借助Spring Boot框架,旨在实现零食交易信息的高效管理,提升用户的购物体验和满意度。 技术栈 开发语言:…...

基于SpringBoot的物流管理系统
作者:计算机学姐 开发技术:SpringBoot、SSM、Vue、MySQL、JSP、ElementUI等,“文末源码”。 专栏推荐:前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 基于JavaSpringBootVueMySQL的物流管理系统【附源码文档】、…...

uniapp微信小程序开发踩坑日记:Pinia持久化报错Cannot read property ‘localStorage‘ of undefined
插件默认使用 localStorage 实现持久化,小程序端不兼容,需要替换持久化 API import { defineStore } from pinia export const useCommonStore defineStore(pack-store, {state: (): State > ({wwInfo: {},globalData: {},timerLock: false, //是…...

负载均衡调度器--LVS
文章目录 集群和分布式集群分布式 LVS介绍LVS特点LVS工作原理LVS集群架构 LVS集群中的术语CIPVIPRSDIPRIP LVS集群的工作模式NAT模式DR模式DR的工作原理DR的特点:DR的网络配置1.配置负载均衡器2.配置后端服务器lo接口的作用 3.测试连接: DR的典型应用场景 TUN模式 L…...

TinyWebSever源码逐行注释(五)_ http_conn.cpp
前言 项目源码地址 项目详细介绍 项目简介: Linux下C轻量级Web服务器,助力初学者快速实践网络编程,搭建属于自己的服务器. 使用 线程池 非阻塞socket epoll(ET和LT均实现) 事件处理(Reactor和模拟Proactor均实现) 的并发模型使用状态机…...