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

Linux下MQTT客户端消息订阅与发布实现

MQTT(消息队列遥测传输)是一个基于客户端-服务器的消息发布/订阅传输协议。它基于TCP协议,默认端口号为1883,为此,它也需要一个消息中间件 。MQTT协议是轻量、简单、开放和易于实现的,这些特点使它适用范围非常广泛。在很多情况下,包括受限的环境中,如:机器与机器(M2M)通信和物联网(IoT),于此同时在智能家居、及一些小型化设备中也已广泛使用。

本文章简单介绍一下MQTT协议的具体应用实现,即客户端模式下消息的订阅与发布实现,运行环境为Linux系统,基于mosquitto这一份开源代码框架改装。具体操作步骤将在下面一一介绍。

  1. 首先下载一份开源的mosquitto代码,编译安装后将产生一系列可执行文件,常用的命令有mosquitto_sub,mosquitto_pub,mosquitto,分别为订阅客户端,发布客户端,以及服务器。

  1. 从mosquitto_sub对应的代码中拷贝一份出来,这里命名为mqtt_client.c,然后对其代码进行修改,整个内容如下:

/*
Copyright (c) 2009-2019 Roger Light <roger@atchoo.org>
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available athttp://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available athttp://www.eclipse.org/org/documents/edl-v10.php.
Contributors:Roger Light - initial implementation and documentation.
*/#include "config.h"
#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#ifndef WIN32
#include <unistd.h>
#include <signal.h>
#else
#include <process.h>
#include <winsock2.h>
#define snprintf sprintf_s
#endif#include "mosquitto.h"
#include "mqtt_protocol.h"
#include "client_shared.h"
#include "pthread.h"struct mosq_config cfg;
bool process_messages = true;
int msg_count = 0;
struct mosquitto *mosq = NULL;
int last_mid = 0;#ifndef WIN32
void my_signal_handler(int signum)
{if(signum == SIGALRM){process_messages = false;}
}
#endifvoid print_message(struct mosq_config *cfg, const struct mosquitto_message *message);/*
发布消息之后运行的回调函数
*/
void my_publish_callback(struct mosquitto *mosq, void *obj, int mid, int reason_code, const mosquitto_property *properties)
{UNUSED(obj);UNUSED(reason_code);UNUSED(properties);
}/*
订阅消息后触发的回调函数,可以在该函数处理接收到的消息,该回调函数必不可少。
*/
void my_message_callback(struct mosquitto *mosq, void *obj, const struct mosquitto_message *message, const mosquitto_property *properties)
{struct mosq_config *cfg;int i;bool res;assert(obj);cfg = (struct mosq_config *)obj;if(message->retain && cfg->no_retain) return;//打印出订阅的主题以及消息长度printf("[%s]topic:%s, payloadlen:%d", __func__, message->topic, message->payloadlen);if(cfg->filter_outs){for(i=0; i<cfg->filter_out_count; i++){mosquitto_topic_matches_sub(cfg->filter_outs[i], message->topic, &res);if(res) return;}}if(cfg->verbose){if(message->payloadlen){fwrite("topic:", 1, strlen("topic:"), stdout);printf("%s ", message->topic);fwrite(message->payload, 1, message->payloadlen, stdout);if(cfg->eol){printf("\n");}}else{if(cfg->eol){printf("%s (null)\n", message->topic);}}fflush(stdout);}else{if(message->payloadlen){
//打印接收到的消息printf("[recv<==]%s\n", message->payload);}}if(cfg->msg_count>0){msg_count++;if(cfg->msg_count == msg_count){process_messages = false;}}}
/*
连接MQTT服务器成功之后触发的回调函数,可在这个函数里面加入订阅主题的功能
*/
void my_connect_callback(struct mosquitto *mosq, void *obj, int result, int flags, const mosquitto_property *properties)
{int i;struct mosq_config *cfg;assert(obj);cfg = (struct mosq_config *)obj;int svrchn;if(!result){for(i=0; i<cfg->topic_count; i++){
//订阅主题的接口mosquitto_subscribe(mosq, NULL, cfg->topics[i], cfg->qos);}}
}
/*
订阅主题成功之后触发的回调函数
*/
void my_subscribe_callback(struct mosquitto *mosq, void *obj, int mid, int qos_count, const int *granted_qos)
{printf("subscribe_callback_v25");int i;struct mosq_config *cfg;assert(obj);cfg = (struct mosq_config *)obj;if(!cfg->quiet) printf("Subscribed (mid: %d): %d\n", mid, granted_qos[0]);for(i=1; i<qos_count; i++){if(!cfg->quiet) printf("%d\n", granted_qos[i]);}if(!cfg->quiet) printf("\n");
}void my_log_callback(struct mosquitto *mosq, void *obj, int level, const char *str)
{UNUSED(mosq);UNUSED(obj);UNUSED(level);printf("%s\n", str);
}
/*
用于发布消息的回调函数,从缓存获取消息,并将该消息发布到服务端,该函数不可缺少。
*/
void mqtt_msg_publish_callback(struct mosquitto *mosq, void *obj, int mid)
{char pubtopic[128]="test/topic";if(msglen) {printf("==>len:%d, topic:%s, msg:%s\n",  msglen,pubtopic, msgbuf);mosquitto_publish(mosq, NULL, pubtopic, msglen, msgbuf, 1, false);msglen = 0;}
}/*
客户端help提示
*/
void print_usage(void)
{int major, minor, revision;mosquitto_lib_version(&major, &minor, &revision);printf("mosquitto_sub is a simple mqtt client that will subscribe to a set of topics and print all messages it receives.\n");printf("mosquitto_sub version %s running on libmosquitto %d.%d.%d.\n\n", "3.1.1", major, minor, revision);printf("Usage: mosquitto_sub {[-h host] [-p port] [-u username] [-P password] -t topic | -L URL [-t topic]}\n");printf("                     [-c] [-k keepalive] [-q qos]\n");printf("                     [-C msg_count] [-E] [-R] [--retained-only] [--remove-retained] [-T filter_out] [-U topic ...]\n");printf("                     [-F format]\n");
#ifndef WIN32printf("                     [-W timeout_secs]\n");
#endif
#ifdef WITH_SRVprintf("                     [-A bind_address] [-S]\n");
#elseprintf("                     [-A bind_address]\n");
#endifprintf("                     [-i id] [-I id_prefix]\n");printf("                     [-d] [-N] [--quiet] [-v]\n");printf("                     [--will-topic [--will-payload payload] [--will-qos qos] [--will-retain]]\n");
#ifdef WITH_TLSprintf("                     [{--cafile file | --capath dir} [--cert file] [--key file]\n");printf("                       [--ciphers ciphers] [--insecure]\n");printf("                       [--tls-alpn protocol]\n");printf("                       [--tls-engine engine] [--keyform keyform] [--tls-engine-kpass-sha1]]\n");
#ifdef FINAL_WITH_TLS_PSKprintf("                     [--psk hex-key --psk-identity identity [--ciphers ciphers]]\n");
#endif
#endif
#ifdef WITH_SOCKSprintf("                     [--proxy socks-url]\n");
#endifprintf("                     [-D command identifier value]\n");printf("       mosquitto_sub --help\n\n");printf(" -A : bind the outgoing socket to this host/ip address. Use to control which interface\n");printf("      the client communicates over.\n");printf(" -c : disable 'clean session' (store subscription and pending messages when client disconnects).\n");printf(" -C : disconnect and exit after receiving the 'msg_count' messages.\n");printf(" -d : enable debug messages.\n");printf(" -D : Define MQTT v5 properties. See the documentation for more details.\n");printf(" -E : Exit once all subscriptions have been acknowledged by the broker.\n");printf(" -F : output format.\n");printf(" -h : mqtt host to connect to. Defaults to localhost.\n");printf(" -i : id to use for this client. Defaults to mosquitto_sub_ appended with the process id.\n");printf(" -I : define the client id as id_prefix appended with the process id. Useful for when the\n");printf("      broker is using the clientid_prefixes option.\n");printf(" -k : keep alive in seconds for this client. Defaults to 60.\n");printf(" -L : specify user, password, hostname, port and topic as a URL in the form:\n");printf("      mqtt(s)://[username[:password]@]host[:port]/topic\n");printf(" -N : do not add an end of line character when printing the payload.\n");printf(" -p : network port to connect to. Defaults to 1883 for plain MQTT and 8883 for MQTT over TLS.\n");printf(" -P : provide a password\n");printf(" -q : quality of service level to use for the subscription. Defaults to 0.\n");printf(" -R : do not print stale messages (those with retain set).\n");
#ifdef WITH_SRVprintf(" -S : use SRV lookups to determine which host to connect to.\n");
#endifprintf(" -t : mqtt topic to subscribe to. May be repeated multiple times.\n");printf(" -T : topic string to filter out of results. May be repeated.\n");printf(" -u : provide a username\n");printf(" -U : unsubscribe from a topic. May be repeated.\n");printf(" -v : print published messages verbosely.\n");printf(" -V : specify the version of the MQTT protocol to use when connecting.\n");printf("      Can be mqttv5, mqttv311 or mqttv31. Defaults to mqttv311.\n");
#ifndef WIN32printf(" -W : Specifies a timeout in seconds how long to process incoming MQTT messages.\n");
#endifprintf(" --help : display this message.\n");printf(" --quiet : don't print error messages.\n");printf(" --retained-only : only handle messages with the retained flag set, and exit when the\n");printf("                   first non-retained message is received.\n");printf(" --remove-retained : send a message to the server to clear any received retained messages\n");printf("                     Use -T to filter out messages you do not want to be cleared.\n");printf(" --will-payload : payload for the client Will, which is sent by the broker in case of\n");printf("                  unexpected disconnection. If not given and will-topic is set, a zero\n");printf("                  length message will be sent.\n");printf(" --will-qos : QoS level for the client Will.\n");printf(" --will-retain : if given, make the client Will retained.\n");printf(" --will-topic : the topic on which to publish the client Will.\n");
#ifdef WITH_TLSprintf(" --cafile : path to a file containing trusted CA certificates to enable encrypted\n");printf("            certificate based communication.\n");printf(" --capath : path to a directory containing trusted CA certificates to enable encrypted\n");printf("            communication.\n");printf(" --cert : client certificate for authentication, if required by server.\n");printf(" --key : client private key for authentication, if required by server.\n");printf(" --keyform : keyfile type, can be either \"pem\" or \"engine\".\n");printf(" --ciphers : openssl compatible list of TLS ciphers to support.\n");printf(" --tls-version : TLS protocol version, can be one of tlsv1.3 tlsv1.2 or tlsv1.1.\n");printf("                 Defaults to tlsv1.2 if available.\n");printf(" --insecure : do not check that the server certificate hostname matches the remote\n");printf("              hostname. Using this option means that you cannot be sure that the\n");printf("              remote host is the server you wish to connect to and so is insecure.\n");printf("              Do not use this option in a production environment.\n");printf(" --tls-engine : If set, enables the use of a SSL engine device.\n");printf(" --tls-engine-kpass-sha1 : SHA1 of the key password to be used with the selected SSL engine.\n");
#ifdef FINAL_WITH_TLS_PSKprintf(" --psk : pre-shared-key in hexadecimal (no leading 0x) to enable TLS-PSK mode.\n");printf(" --psk-identity : client identity string for TLS-PSK mode.\n");
#endif
#endif
#ifdef WITH_SOCKSprintf(" --proxy : SOCKS5 proxy URL of the form:\n");printf("           socks5h://[username[:password]@]hostname[:port]\n");printf("           Only \"none\" and \"username\" authentication is supported.\n");
#endifprintf("\nSee https://mosquitto.org/ for more information.\n\n");
}/*
在这里定义消息缓存及消息长度
*/
char msgbuf[512];
int msglen;/*
从终端接手输入的信息,并存入缓存
*/
void *mqtt_publish_hander(void *arg)
{struct mosquitto *mosq = (struct mosquitto *)arg;while(1) {char pubtopic[128]="test/topic";char testbuf[512]="";printf("please input some thing:\n");fgets(msgbuf, sizeof(msgbuf), stdin);msglen = strlen(msgbuf);}
}
/*
开启一个线程,用来处理输入的信息
*/
void mqtt_msg_publish_proc(struct mosquitto *mosq)
{pthread_t TaskId;pthread_attr_t att;pthread_attr_init(&att);pthread_attr_setdetachstate(&att, PTHREAD_CREATE_DETACHED);int result = pthread_create(&TaskId, &att, mqtt_publish_hander, (void *)mosq);
}/*
客户端程序入口函数
*/
int main(int argc, char *argv[])
{int rc;
#ifndef WIN32struct sigaction sigact;
#endifmosquitto_lib_init();rc = client_config_load(&cfg, CLIENT_SUB, argc, argv);if(rc){if(rc == 2){/* --help */print_usage();}else{fprintf(stderr, "\nUse 'mosquitto_sub --help' to see usage.\n");}goto cleanup;}if(cfg.no_retain && cfg.retained_only){fprintf(stderr, "\nError: Combining '-R' and '--retained-only' makes no sense.\n");goto cleanup;}if(client_id_generate(&cfg,"mosqsub")){goto cleanup;}mosq = mosquitto_new(cfg.id, cfg.clean_session, &cfg);if(!mosq){switch(errno){case ENOMEM://err_printf(&cfg, "Error: Out of memory.\n");break;case EINVAL://err_printf(&cfg, "Error: Invalid id and/or clean_session.\n");break;}goto cleanup;}if(client_opts_set(mosq, &cfg)){goto cleanup;}if(cfg.debug){mosquitto_log_callback_set(mosq, my_log_callback);mosquitto_subscribe_callback_set(mosq, my_subscribe_callback);}mosquitto_connect_v5_callback_set(mosq, my_connect_callback);mosquitto_message_v5_callback_set(mosq, my_message_callback);mosquitto_misc_callback_set(mosq, mqtt_msg_publish_callback);rc = client_connect(mosq, &cfg);if(rc){goto cleanup;}#ifndef WIN32sigact.sa_handler = my_signal_handler;sigemptyset(&sigact.sa_mask);sigact.sa_flags = 0;if(sigaction(SIGALRM, &sigact, NULL) == -1){perror("sigaction");goto cleanup;}if(cfg.timeout){alarm(cfg.timeout);}
#endif//连接成功之后,开启线程mqtt_msg_publish_proc(mosq);//循环事件处理,遇到异常事件将退出该循环rc = mosquitto_loop_forever(mosq, -1, 1);mosquitto_destroy(mosq);mosquitto_lib_cleanup();if(cfg.msg_count>0 && rc == MOSQ_ERR_NO_CONN){rc = 0;}client_config_cleanup(&cfg);if(rc){//err_printf(&cfg, "Error: %s\n", mosquitto_strerror(rc));}return rc;cleanup:mosquitto_lib_cleanup();client_config_cleanup(&cfg);return 1;
}
  1. 编译客户端程序,生成一个名为”mqtt_client”的可执行文件。

  1. 在服务端开启 mosquitto服务端。

运行命令:mosquitto -c /etc/mosquitto/mosquitto.conf&

如下图所示:

5.mqtt_client客户端消息发布。

运行客户端程序,如下图所示:

./mqtt_client -h 192.168.9.68 -p 1883 -t "subtopic/test"

参数说明:

-h:指定mqtt服务端地址

-p:指定mqtt服务端端口

-t:用于接收数据的订阅主题

运行订阅客户端mosquitto_sub,用来接收消息,如下图所示:

由上图可知,mqtt_client发布的消息已经被正确接收。

6.mqtt_client客户端消息订阅

运行发布客户端mosquitto_pub,给mqtt_client发布消息,如下所示:

从mqtt_client客户端查看消息订阅结果,如下图所示:

至此,mqtt_client客户端程序的发布与订阅功能已经基本验证完毕。

总结:经过修改的MQTT客户端程序,可以实现与服务端接入,为以后诸多领域下的终端、网关设备接入云平台提供了简单的实例,后期可基于该程序根据具体的业务进行完善以及优化,给开发人员或者运维人员提供方便。MQTT由于开放源代码,耗电量小等特点,将会其它消息推送领域会有更多的贡献,例如在物联网领域,传感器与服务器的通信,信息的收集,MQTT都可以作为考虑的方案之一。在未来MQTT会进入到我们生活的各个方面。

相关文章:

Linux下MQTT客户端消息订阅与发布实现

MQTT(消息队列遥测传输)是一个基于客户端-服务器的消息发布/订阅传输协议。它基于TCP协议&#xff0c;默认端口号为1883&#xff0c;为此&#xff0c;它也需要一个消息中间件 。MQTT协议是轻量、简单、开放和易于实现的&#xff0c;这些特点使它适用范围非常广泛。在很多情况下…...

代码规范----编程规约(下)

目录 四、OOP规约 五、日期时间 六、集合处理 四、OOP规约 &#xff08;1&#xff09;、避免通过一个类的对象引用访问此类的静态变量或静态方法&#xff0c;无谓增加编译器解析成本&#xff0c;直接用类名来访问即可 &#xff08;2&#xff09;、所有的覆写方法&#xff0…...

c++连接mysql

开始想用mysql connector/c8.0 来操作数据库cmake加上配置后一直编译错误 我这里也没有截屏编译错误大概意思是driver.h里面声明的一个check_lib函数里面用了一个未定义的check找遍了资料都没有找到解决办法最后还是用了原始API如果有人有解决办法请留个位置先上在用的cmake配置…...

CentOS7操作系统安装nginx实战(多种方法,超详细)

文章目录前言一. 实验环境二. 使用yum安装nginx2.1 添加yum源2.1.1 使用官网提供的源地址&#xff08;方法一&#xff09;2.1.2 使用epel的方式进行安装&#xff08;方法二&#xff09;2.2 开始安装nginx2.3 启动并进行测试2.4 其他的一些用法&#xff1a;三. 编译方式安装ngin…...

【测绘程序设计】——空间直角坐标转换

测绘工程中经常遇到空间直角坐标转换——比如,北京54(或西安80)空间直角坐标转换成CGCS2000(或WGS-84)空间直角坐标,常用转换模型包括:①布尔沙模型(国家级及省级范围);②莫洛坚斯基模型(省级以下范围);③三维四参数(小于22局部区域) 等。   本文分享了基于布…...

数组--java--动态数组--有序数组--底层

java数组基础--java中的数组创建数组空间占用初始化数组访问元素插入查找删除元素动态数组扩容插入和添加重写toString删除二维数组二维数组注意点有序数组实现测试写在开头&#xff1a; 这篇文章包括数组的基础、一点底层的内容和一些稍微深入的东西。 作为第一个深入学习的数…...

Linux下使用C语言实现简单的聊天室程序

本文章介绍一种基于Linux使用C语言实现简单的局域网聊天室程序的方法&#xff0c;支持消息群发&#xff0c;历史数据查询&#xff0c;好友列表查看&#xff0c;好友上线下线提醒等功能。聊天界面如下图所示&#xff1a;下面将按步骤介绍该系统的设计实现&#xff0c;首先在linu…...

【数学】任意一个正整数n最多只有一个质因数大于根号n,怎么证明?

定理 任意一个正整数n最多只有一个大于n\sqrt{n}n​的质因子&#xff0c;并且该大于n\sqrt{n}n​质因子的幂次是1。 证明&#xff08;反证法&#xff09; 证明&#xff1a;最多只有一个大于n\sqrt{n}n​的质因子 假设n存在两个大于n\sqrt{n}n​的质因子&#xff0c;分别为p…...

【ES6】var let const 之面试题系列

关于 var、let、const 是前端开发人员经常用到的关键字&#xff0c;也是经典的面试题&#xff0c;接下来就站在面试题的角度来看待它们之间的区别。 一、区别 1. var 声明的范围是函数作用域&#xff0c;let 和 const 声明的范围是块作用域&#xff0c;块作用域是函数作用域的…...

Vue基础入门讲义(四)-组件化

文章目录1.引言2.定义全局组件3.组件的复用4.局部注册5.组件通信5.1.父向子传递props5.2.传递复杂数据5.3.子向父的通信1.引言 在大型应用开发的时候&#xff0c;页面可以划分成很多部分。往往不同的页面&#xff0c;也会有相同的部分。例如可能会有相同的头部导航。 但是如果…...

Android onLayout布局流程解析

组件布局流程结论 1.&#xff09;layout流程始于ViewRootImpl的performLayout()方法&#xff0c;该方法会调用根View&#xff08;DecorView&#xff09;的layout()方法进行布局&#xff0c;因为DecorView是ViewGroup(FrameLayout),所以layout流程来到了ViewGroup&#xff08;其…...

浅分析BIG-建筑展示系统

一、主页&#xff08;主要界面&#xff09;重点疑点&#xff08;需要解决&#xff09;1.云平台实时同步。是否可以电脑与hololens2同步或链接&#xff1f;并可以传输信息提醒&#xff1f;一级界面&#xff08;启动界面&#xff09;1.交互式启动激活效果&#xff08;触发按钮旋转…...

模电基础(1) 半导体基础知识

基本内容&#xff1a; 1.本征半导体的基本介绍结构&#xff1b; 2.杂质半导体&#xff1b; 3.PN结的形成&#xff1b; 4.PN结的性质。 1.本征半导体 半导体&#xff1a;导电性能介于绝缘体和导体之间的物质。 本征半导体是纯净的晶体结构的半导体。 纯净→无杂质晶体结构→稳…...

阅读笔记:TF - IDF 原理

今天查阅 TF-IDF 资料&#xff0c;发现百度百科里面提供了一个例子&#xff0c;解释的很清楚&#xff0c;记下来备用。 原文链接&#xff1a;https://baike.baidu.com/item/tf-idf/8816134?fraladdin 例子&#xff1a;在某个一共有一千词的网页中 “原子能”、“的” 和 “应…...

【C语言】float 关键字

&#x1f6a9;write in front&#x1f6a9; &#x1f50e;大家好&#xff0c;我是謓泽&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流&#x1f50e; &#x1f3c5;2021|2022年度博客之星物联网与嵌入式开发TOP5|TOP4…...

Linux 网络编程(实现多路IO转接服务器)

1.select函数实现多路IO转接服务器select函数原型&#xff1a;包含在头文件<sys/time.h>&#xff0c;<sys/types.h>和<unistd.h>int select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout);作用&#xff1a;确定…...

DC-4 靶场学习

信息搜集&#xff1a; 首先获取靶场ip&#xff0c;和之前一样。 arp-scan -l nmap -sP 192.168.28.0/24然后访问。 发现需要登录。 漏洞分析: 直接用bp爆破&#xff0c;爆破出来密码为happy&#xff0c;登录。 发现执行了命令&#xff0c;抓包。 修改命令可以执行&#xff…...

QML组件

一个QML文件定义了一个独立的、顶级的QML组件。 一个QML组件就是一个模板&#xff0c;被QML运行环境解释来创建一个带有一些预定义行为的对象。 一个独立的QML组件可以运行多次来禅城多个对象&#xff0c;每个对象都可以称为该组件的实例。 例子&#xff1a; 在项目中添加一…...

canvas 学习指南

canvas 学习指南 创建一个 canvas <! DOCTYPE html><html xmlns"http://www.w3.org/1999/xhtml"><head><title></title><meta charset"utf-8" /><script type"text/javascript">window.onload fun…...

【华为OD机试2023】开心消消乐 C++

【华为OD机试2023】开心消消乐 C++ 前言 如果您在准备华为的面试,期间有想了解的可以私信我,我会尽可能帮您解答,也可以给您一些建议! 本文解法非最优解(即非性能最优),不能保证通过率。 Tips1:机试为ACM 模式 你的代码需要处理输入输出,input/cin接收输入、print/cou…...

rknn优化教程(二)

文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK&#xff0c;开始写第二篇的内容了。这篇博客主要能写一下&#xff1a; 如何给一些三方库按照xmake方式进行封装&#xff0c;供调用如何按…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器

一.自适应梯度算法Adagrad概述 Adagrad&#xff08;Adaptive Gradient Algorithm&#xff09;是一种自适应学习率的优化算法&#xff0c;由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率&#xff0c;适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

css的定位(position)详解:相对定位 绝对定位 固定定位

在 CSS 中&#xff0c;元素的定位通过 position 属性控制&#xff0c;共有 5 种定位模式&#xff1a;static&#xff08;静态定位&#xff09;、relative&#xff08;相对定位&#xff09;、absolute&#xff08;绝对定位&#xff09;、fixed&#xff08;固定定位&#xff09;和…...

免费数学几何作图web平台

光锐软件免费数学工具&#xff0c;maths,数学制图&#xff0c;数学作图&#xff0c;几何作图&#xff0c;几何&#xff0c;AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...

MinIO Docker 部署:仅开放一个端口

MinIO Docker 部署:仅开放一个端口 在实际的服务器部署中,出于安全和管理的考虑,我们可能只能开放一个端口。MinIO 是一个高性能的对象存储服务,支持 Docker 部署,但默认情况下它需要两个端口:一个是 API 端口(用于存储和访问数据),另一个是控制台端口(用于管理界面…...

通过 Ansible 在 Windows 2022 上安装 IIS Web 服务器

拓扑结构 这是一个用于通过 Ansible 部署 IIS Web 服务器的实验室拓扑。 前提条件&#xff1a; 在被管理的节点上安装WinRm 准备一张自签名的证书 开放防火墙入站tcp 5985 5986端口 准备自签名证书 PS C:\Users\azureuser> $cert New-SelfSignedCertificate -DnsName &…...

2.3 物理层设备

在这个视频中&#xff0c;我们要学习工作在物理层的两种网络设备&#xff0c;分别是中继器和集线器。首先来看中继器。在计算机网络中两个节点之间&#xff0c;需要通过物理传输媒体或者说物理传输介质进行连接。像同轴电缆、双绞线就是典型的传输介质&#xff0c;假设A节点要给…...

在Zenodo下载文件 用到googlecolab googledrive

方法&#xff1a;Figshare/Zenodo上的数据/文件下载不下来&#xff1f;尝试利用Google Colab &#xff1a;https://zhuanlan.zhihu.com/p/1898503078782674027 参考&#xff1a; 通过Colab&谷歌云下载Figshare数据&#xff0c;超级实用&#xff01;&#xff01;&#xff0…...

FOPLP vs CoWoS

以下是 FOPLP&#xff08;Fan-out panel-level packaging 扇出型面板级封装&#xff09;与 CoWoS&#xff08;Chip on Wafer on Substrate&#xff09;两种先进封装技术的详细对比分析&#xff0c;涵盖技术原理、性能、成本、应用场景及市场趋势等维度&#xff1a; 一、技术原…...

CMS内容管理系统的设计与实现:多站点模式的实现

在一套内容管理系统中&#xff0c;其实有很多站点&#xff0c;比如企业门户网站&#xff0c;产品手册&#xff0c;知识帮助手册等&#xff0c;因此会需要多个站点&#xff0c;甚至PC、mobile、ipad各有一个站点。 每个站点关联的有站点所在目录及所属的域名。 一、站点表设计…...