【MQTT】paho.mqtt.c 库的“介绍、下载、交叉编译” 详解,以及编写MQTT客户端例子源码

😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀
🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C++、数据结构、音视频🍭
⏰发布时间⏰:2024-05-13 12:43:09

本文未经允许,不得转发!!!

目录

  • 🎄一、概述
  • 🎄二、paho.mqtt.c库介绍
    • ✨2.1 异步的paho.mqtt.c库(Asynchronous MQTT client library for C)
    • ✨2.2 同步的paho.mqtt.c库(MQTT Client library for C)
    • ✨2.3 异步和同步库的区别(Asynchronous vs synchronous client applications)
  • 🎄三、paho.mqtt.c 库的下载、交叉编译
    • ✨3.1 openssl 的下载、交叉编译
    • ✨3.2 paho.mqtt.c 交叉编译
  • 🎄四、paho.mqtt.c库写一个MQTT客户端
    • ✨4.1 订阅——MQTTAsync_subscribe.c
    • ✨4.2 发布——MQTTAsync_publish.c
  • 🎄五、总结


在这里插入图片描述

在这里插入图片描述

🎄一、概述

上篇文章 【MQTT】mosquitto 的 “下载、交叉编译、使用” 详细教程,手把手搭建一个MQTT Broker ,介绍了怎样搭建一个MQTT Broker(代理)。MQTT Broker(代理)的搭建很重要,一般很少自己开发一个MQTT Broker,而是搭建好一个开源的MQTT Broker(代理),然后其他的设备或机器都作为MQTT客户端,让MQTT Broker来转发消息。

关于MQTT协议的,作为编程人员更多的是开发MQTT的客户端,本文介绍的paho.mqtt.c就是开发MQTT客户端常用的开源库之一。paho.mqtt.cEclipse Paho 项目的一个开源库。

Eclipse Paho项目提供了以各种编程语言实现的MQTT和MQTT-SN的开源库(主要是客户端)。下面是这个项目的MQTT客户端开源库,想要了解更多Eclipse Paho项目的资料,可以到其官网:https://eclipse.dev/paho/
在这里插入图片描述


在这里插入图片描述

🎄二、paho.mqtt.c库介绍

paho.mqtt.c库编译后会生成四个动态库,:

  • libpaho-mqtt3a.so:异步的paho.mqtt.c库
  • libpaho-mqtt3as.so:异步的、使用了SSL的paho.mqtt.c库
  • libpaho-mqtt3c.so:经典的、同步的paho.mqtt.c库
  • libpaho-mqtt3cs.so:经典的、同步的、使用了SSL的paho.mqtt.c库

✨2.1 异步的paho.mqtt.c库(Asynchronous MQTT client library for C)

关于异步的paho.mqtt.c库可以参考其官网文章:Asynchronous MQTT client library for C

这里只摘要了使用方法,异步的paho.mqtt.c库有如下相似的使用框架:

  • 1.创建一个客户端对象;
  • 2.设置连接MQTT服务器的选项;
  • 3.设置回调函数;
  • 4.将客户端和服务器连接;
  • 5.订阅客户端需要接收的所有话题;
  • 6.重复以下操作直到结束:
    • a.发布客户端需要的任意信息;
    • b.处理所有接收到的信息;
  • 7.断开客户端连接;
  • 8.释放客户端使用的所有内存。

✨2.2 同步的paho.mqtt.c库(MQTT Client library for C)

关于异步的paho.mqtt.c库可以参考其官网文章:MQTT Client library for C

这里只摘要了使用方法,同步的paho.mqtt.c库有如下相似的使用框架:

  • 1.创建一个客户端对象;
  • 2.设置连接MQTT服务器的选项;
  • 3.如果要使用多线程(异步模式)操作,则调用 MQTTClient_setCallbacks() 设置回调函数;
  • 4.订阅客户端需要接收的任意话题;
  • 5.重复以下操作直到结束:
    • a.发布客户端需要的任意信息;
    • b.处理所有接收到的信息;
  • 6.断开客户端连接;
  • 7.释放客户端使用的所有内存。

✨2.3 异步和同步库的区别(Asynchronous vs synchronous client applications)

下面是译文,原文地址:Asynchronous vs synchronous client applications

客户端库支持两种操作模式。这些模式被称为同步模式异步模式。如果您的应用程序调用 MQTTClient_setCallbacks(),这将使客户端进入异步模式,否则它将以同步模式运行。

在同步模式下,客户端应用程序在单个线程上运行。消息是使用 MQTTClient_publish() 和 MQTTClient_publishMessage() 函数发布的。要确定QoS1或QoS2(请参阅Quality of service)消息已成功传递,应用程序必须调用 MQTTClient_waitForCompletion() 函数。Synchronous publication example 中展示了一个同步发布的示例。在同步模式下接收消息使用MQTTClient_receive()函数。客户端应用程序必须相对频繁地调用MQTTClient_ereceived()或MQTTClient_yield(),以便允许(执行)确认和保持与服务器的网络连接的 MQTT “ping” 操作。

在异步模式下,客户端应用程序在多个线程上运行。主程序像同步模式一样地调用客户端库中的函数来发布和订阅。然而,握手和保持网络连接的处理是在后台执行的。通过调用 MQTTClient_setCallbacks(),使用在库中注册的回调将状态和消息接收通知提供给客户端应用程序(请参阅 MQTTClient_messageArrived()、MQTTClient_connectionLost() 和MQTTClient_edeliveryComplete() )。然而,这个API不是线程安全的——在没有同步的情况下,不可能从多个线程调用它。您可以使用MQTTAsync API来实现这一点。


在这里插入图片描述

🎄三、paho.mqtt.c 库的下载、交叉编译

本文下载的是paho.mqtt.c-1.3.13.tar.gz,下载地址:https://github.com/eclipse/paho.mqtt.c/archive/refs/tags/v1.3.13.tar.gz

编译 paho.mqtt.c 库之前,需要先编译其依赖库:openssl。

✨3.1 openssl 的下载、交叉编译

本文下载的是 openssl-OpenSSL_1_1_1g.tar.gz
下载地址:https://codeload.github.com/openssl/openssl/tar.gz/refs/tags/OpenSSL_1_1_1g
为什么使用这么旧的版本,因为这个我之前编译过,而且使用没问题。

编译步骤:

  • 1、解压缩

    tar zxf openssl-OpenSSL_1_1_1g.tar.gz
    
  • 2、进入目录,并配置输出目录和交叉编译器, (linux-generic32表示是32位操作系统,个别文章加了这个选项就不用去掉 -m64,我这里行不通)

    cd openssl-OpenSSL_1_1_1g/
    ./config no-asm shared no-async --prefix=`pwd`/ssl_result  --cross-compile-prefix=aarch64-mix210-linux-
    
  • 3、执行下面命令,删除Makefile文件的 -m64

    sed -i 's/-m64//' Makefile
    

    执行后,可以避免出现这个编译错误:aarch64-mix210-linux-gcc: error: unrecognized command line option '-m64'

  • 4、编译、安装

    make && make install
    

成功编译后,在openssl-OpenSSL_1_1_1g/目录会生成一个ssl_result目录,可以看到里面生成的库:
在这里插入图片描述


✨3.2 paho.mqtt.c 交叉编译

编译步骤:

  • 1、解压缩,创建要安装目录paho.mqtt.c_result

    tar zxf paho.mqtt.c-1.3.13.tar.gz
    
    mkdir paho.mqtt.c_result/bin -p
    mkdir paho.mqtt.c_result/include -p
    mkdir paho.mqtt.c_result/lib -p
    mkdir paho.mqtt.c_result/share/man/man1 -p
    
  • 2、进入目录,交叉编译

    cd paho.mqtt.c-1.3.13/
    make  CC=aarch64-mix210-linux-gcc CFLAGS:="-I `pwd`/../ssl_result/include" LDFLAGS:="-L `pwd`/../ssl_result/lib"
    

    CFLAGS:=“-I `pwd`/…/ssl_result/include”:指定前面编译的 openssl 的头文件;
    LDFLAGS:=“-L `pwd`/…/ssl_result/lib”:指定前面编译的 openssl 的库文件路径;

  • 3、make install,安装编译结果

    make install prefix=`pwd`/../paho.mqtt.c_result 
    

    prefix=`pwd`/…/paho.mqtt.c_result :指定安装目录路径;

编译完成后,会生成 目录,内容如下:
在这里插入图片描述


在这里插入图片描述

🎄四、paho.mqtt.c库写一个MQTT客户端

下面提供两个使用了 paho.mqtt.c库(libpaho-mqtt3a) MQTT客户端的例子。

运行下面代码前,要先搭建一个MQTT Broker,参考上篇文章:【MQTT】mosquitto 的 “下载、交叉编译、使用” 详细教程,手把手搭建一个MQTT Broker

✨4.1 订阅——MQTTAsync_subscribe.c

这是使用了 libpaho-mqtt3a.so 进行订阅消息的源码,源码路径在源码的这个路径:paho.mqtt.c-1.3.13/src/samples/MQTTAsync_subscribe.c,只更改了服务器地址。完整代码如下:

/*******************************************************************************
 * Copyright (c) 2012, 2022 IBM Corp., Ian Craggs
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v2.0
 * and Eclipse Distribution License v1.0 which accompany this distribution. 
 *
 * The Eclipse Public License is available at 
 *   https://www.eclipse.org/legal/epl-2.0/
 * and the Eclipse Distribution License is available at 
 *   http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * Contributors:
 *    Ian Craggs - initial contribution
 *******************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "MQTTAsync.h"

#if !defined(_WIN32)
#include <unistd.h>
#else
#include <windows.h>
#endif

#if defined(_WRS_KERNEL)
#include <OsWrapper.h>
#endif

#define ADDRESS     "192.168.3.227:1883"
#define CLIENTID    "ExampleClientSub"
#define TOPIC       "MQTT Examples"
#define PAYLOAD     "Hello World!"
#define QOS         1
#define TIMEOUT     10000L

int disc_finished = 0;
int subscribed = 0;
int finished = 0;

void onConnect(void* context, MQTTAsync_successData* response);
void onConnectFailure(void* context, MQTTAsync_failureData* response);

void connlost(void *context, char *cause)
{
	MQTTAsync client = (MQTTAsync)context;
	MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer;
	int rc;

	printf("\nConnection lost\n");
	if (cause)
		printf("     cause: %s\n", cause);

	printf("Reconnecting\n");
	conn_opts.keepAliveInterval = 20;
	conn_opts.cleansession = 1;
	conn_opts.onSuccess = onConnect;
	conn_opts.onFailure = onConnectFailure;
	if ((rc = MQTTAsync_connect(client, &conn_opts)) != MQTTASYNC_SUCCESS)
	{
		printf("Failed to start connect, return code %d\n", rc);
		finished = 1;
	}
}


int msgarrvd(void *context, char *topicName, int topicLen, MQTTAsync_message *message)
{
    printf("Message arrived\n");
    printf("     topic: %s\n", topicName);
    printf("   message: %.*s\n", message->payloadlen, (char*)message->payload);
    MQTTAsync_freeMessage(&message);
    MQTTAsync_free(topicName);
    return 1;
}

void onDisconnectFailure(void* context, MQTTAsync_failureData* response)
{
	printf("Disconnect failed, rc %d\n", response->code);
	disc_finished = 1;
}

void onDisconnect(void* context, MQTTAsync_successData* response)
{
	printf("Successful disconnection\n");
	disc_finished = 1;
}

void onSubscribe(void* context, MQTTAsync_successData* response)
{
	printf("Subscribe succeeded\n");
	subscribed = 1;
}

void onSubscribeFailure(void* context, MQTTAsync_failureData* response)
{
	printf("Subscribe failed, rc %d\n", response->code);
	finished = 1;
}


void onConnectFailure(void* context, MQTTAsync_failureData* response)
{
	printf("Connect failed, rc %d\n", response->code);
	finished = 1;
}


void onConnect(void* context, MQTTAsync_successData* response)
{
	MQTTAsync client = (MQTTAsync)context;
	MQTTAsync_responseOptions opts = MQTTAsync_responseOptions_initializer;
	int rc;

	printf("Successful connection\n");

	printf("Subscribing to topic %s\nfor client %s using QoS%d\n\n"
           "Press Q<Enter> to quit\n\n", TOPIC, CLIENTID, QOS);
	opts.onSuccess = onSubscribe;
	opts.onFailure = onSubscribeFailure;
	opts.context = client;
	if ((rc = MQTTAsync_subscribe(client, TOPIC, QOS, &opts)) != MQTTASYNC_SUCCESS)
	{
		printf("Failed to start subscribe, return code %d\n", rc);
		finished = 1;
	}
}


int main(int argc, char* argv[])
{
	MQTTAsync client;
	MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer;
	MQTTAsync_disconnectOptions disc_opts = MQTTAsync_disconnectOptions_initializer;
	int rc;
	int ch;

	if ((rc = MQTTAsync_create(&client, ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL))
			!= MQTTASYNC_SUCCESS)
	{
		printf("Failed to create client, return code %d\n", rc);
		rc = EXIT_FAILURE;
		goto exit;
	}

	if ((rc = MQTTAsync_setCallbacks(client, client, connlost, msgarrvd, NULL)) != MQTTASYNC_SUCCESS)
	{
		printf("Failed to set callbacks, return code %d\n", rc);
		rc = EXIT_FAILURE;
		goto destroy_exit;
	}

	conn_opts.keepAliveInterval = 20;
	conn_opts.cleansession = 1;
	conn_opts.onSuccess = onConnect;
	conn_opts.onFailure = onConnectFailure;
	conn_opts.context = client;
	if ((rc = MQTTAsync_connect(client, &conn_opts)) != MQTTASYNC_SUCCESS)
	{
		printf("Failed to start connect, return code %d\n", rc);
		rc = EXIT_FAILURE;
		goto destroy_exit;
	}

	while (!subscribed && !finished)
		#if defined(_WIN32)
			Sleep(100);
		#else
			usleep(10000L);
		#endif

	if (finished)
		goto exit;

	do 
	{
		ch = getchar();
	} while (ch!='Q' && ch != 'q');

	disc_opts.onSuccess = onDisconnect;
	disc_opts.onFailure = onDisconnectFailure;
	if ((rc = MQTTAsync_disconnect(client, &disc_opts)) != MQTTASYNC_SUCCESS)
	{
		printf("Failed to start disconnect, return code %d\n", rc);
		rc = EXIT_FAILURE;
		goto destroy_exit;
	}
 	while (!disc_finished)
 	{
		#if defined(_WIN32)
			Sleep(100);
		#else
			usleep(10000L);
		#endif
 	}

destroy_exit:
	MQTTAsync_destroy(&client);
exit:
 	return rc;
}

交叉编译:

aarch64-mix210-linux-gcc MQTTAsync_subscribe.c -I paho.mqtt.c_result/include/ -L paho.mqtt.c_result/lib/ -l paho-mqtt3a -o MQTTAsync_subscribe

在嵌入式板子运行:

在这里插入图片描述


✨4.2 发布——MQTTAsync_publish.c

这是使用了 libpaho-mqtt3a.so 进行发布消息的源码,源码路径在源码的这个路径:paho.mqtt.c-1.3.13/src/samples/MQTTAsync_publish.c,只更改了服务器地址。完整代码如下:

/*******************************************************************************
 * Copyright (c) 2012, 2023 IBM Corp., Ian Craggs
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v2.0
 * and Eclipse Distribution License v1.0 which accompany this distribution. 
 *
 * The Eclipse Public License is available at 
 *   https://www.eclipse.org/legal/epl-2.0/
 * and the Eclipse Distribution License is available at 
 *   http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * Contributors:
 *    Ian Craggs - initial contribution
 *******************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "MQTTAsync.h"

#if !defined(_WIN32)
#include <unistd.h>
#else
#include <windows.h>
#endif

#if defined(_WRS_KERNEL)
#include <OsWrapper.h>
#endif

#define ADDRESS     "192.168.3.227:1883"
#define CLIENTID    "ExampleClientPub"
#define TOPIC       "MQTT Examples"
#define PAYLOAD     "Hello World!"
#define QOS         2
#define TIMEOUT     10000L

int finished = 0;

void connlost(void *context, char *cause)
{
	MQTTAsync client = (MQTTAsync)context;
	MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer;
	int rc;

	printf("\nConnection lost\n");
	if (cause)
		printf("     cause: %s\n", cause);

	printf("Reconnecting\n");
	conn_opts.keepAliveInterval = 20;
	conn_opts.cleansession = 1;
	if ((rc = MQTTAsync_connect(client, &conn_opts)) != MQTTASYNC_SUCCESS)
	{
		printf("Failed to start connect, return code %d\n", rc);
 		finished = 1;
	}
}

void onDisconnectFailure(void* context, MQTTAsync_failureData* response)
{
	printf("Disconnect failed\n");
	finished = 1;
}

void onDisconnect(void* context, MQTTAsync_successData* response)
{
	printf("Successful disconnection\n");
	finished = 1;
}

void onSendFailure(void* context, MQTTAsync_failureData* response)
{
	MQTTAsync client = (MQTTAsync)context;
	MQTTAsync_disconnectOptions opts = MQTTAsync_disconnectOptions_initializer;
	int rc;

	printf("Message send failed token %d error code %d\n", response->token, response->code);
	opts.onSuccess = onDisconnect;
	opts.onFailure = onDisconnectFailure;
	opts.context = client;
	if ((rc = MQTTAsync_disconnect(client, &opts)) != MQTTASYNC_SUCCESS)
	{
		printf("Failed to start disconnect, return code %d\n", rc);
		exit(EXIT_FAILURE);
	}
}

void onSend(void* context, MQTTAsync_successData* response)
{
	MQTTAsync client = (MQTTAsync)context;
	MQTTAsync_disconnectOptions opts = MQTTAsync_disconnectOptions_initializer;
	int rc;

	printf("Message with token value %d delivery confirmed\n", response->token);
	opts.onSuccess = onDisconnect;
	opts.onFailure = onDisconnectFailure;
	opts.context = client;
	if ((rc = MQTTAsync_disconnect(client, &opts)) != MQTTASYNC_SUCCESS)
	{
		printf("Failed to start disconnect, return code %d\n", rc);
		exit(EXIT_FAILURE);
	}
}


void onConnectFailure(void* context, MQTTAsync_failureData* response)
{
	printf("Connect failed, rc %d\n", response ? response->code : 0);
	finished = 1;
}


void onConnect(void* context, MQTTAsync_successData* response)
{
	MQTTAsync client = (MQTTAsync)context;
	MQTTAsync_responseOptions opts = MQTTAsync_responseOptions_initializer;
	MQTTAsync_message pubmsg = MQTTAsync_message_initializer;
	int rc;

	printf("Successful connection\n");
	opts.onSuccess = onSend;
	opts.onFailure = onSendFailure;
	opts.context = client;
	pubmsg.payload = PAYLOAD;
	pubmsg.payloadlen = (int)strlen(PAYLOAD);
	pubmsg.qos = QOS;
	pubmsg.retained = 0;
	if ((rc = MQTTAsync_sendMessage(client, TOPIC, &pubmsg, &opts)) != MQTTASYNC_SUCCESS)
	{
		printf("Failed to start sendMessage, return code %d\n", rc);
		exit(EXIT_FAILURE);
	}
}

int messageArrived(void* context, char* topicName, int topicLen, MQTTAsync_message* m)
{
	/* not expecting any messages */
	return 1;
}

int main(int argc, char* argv[])
{
	MQTTAsync client;
	MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer;
	int rc;

	if ((rc = MQTTAsync_create(&client, ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL)) != MQTTASYNC_SUCCESS)
	{
		printf("Failed to create client object, return code %d\n", rc);
		exit(EXIT_FAILURE);
	}

	if ((rc = MQTTAsync_setCallbacks(client, client, connlost, messageArrived, NULL)) != MQTTASYNC_SUCCESS)
	{
		printf("Failed to set callback, return code %d\n", rc);
		exit(EXIT_FAILURE);
	}

	conn_opts.keepAliveInterval = 20;
	conn_opts.cleansession = 1;
	conn_opts.onSuccess = onConnect;
	conn_opts.onFailure = onConnectFailure;
	conn_opts.context = client;
	if ((rc = MQTTAsync_connect(client, &conn_opts)) != MQTTASYNC_SUCCESS)
	{
		printf("Failed to start connect, return code %d\n", rc);
		exit(EXIT_FAILURE);
	}

	printf("Waiting for publication of %s\n"
         "on topic %s for client with ClientID: %s\n",
         PAYLOAD, TOPIC, CLIENTID);
	while (!finished)
		#if defined(_WIN32)
			Sleep(100);
		#else
			usleep(10000L);
		#endif

	MQTTAsync_destroy(&client);
 	return rc;
}

交叉编译:

aarch64-mix210-linux-gcc MQTTAsync_publish.c -I paho.mqtt.c_result/include/ -L paho.mqtt.c_result/lib/ -l paho-mqtt3a -o MQTTAsync_publish

在嵌入式板子的运行结果:
在这里插入图片描述


在这里插入图片描述

🎄五、总结

👉本文详细介绍了 paho.mqtt.c 库的“介绍、下载、交叉编译” ,以及怎么使用 aho.mqtt.c 库 编写MQTT客户端例子源码。

在这里插入图片描述
如果文章有帮助的话,点赞👍、收藏⭐,支持一波,谢谢 😁😁😁

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/622823.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ubuntu 22.04 安装 RTX 4090 显卡驱动 GPU Driver(PyTorch准备)

文章目录 1. 参考文章2. 检查GPU是Nvidia3. 卸载已有驱动3.1. 命令删除3.2. 老驱动包 4. 官网下载驱动5. 运行5.1. 远程安装关闭交互界面5.2. 运行5.3. 打开交互界面 6. 检测与后续安装 1. 参考文章 https://blog.csdn.net/JineD/article/details/129432308 2. 检查GPU是Nvid…

02-WPF_基础(二)

3、控件学习 控件学习 布局控件&#xff1a; panel、Grid 内容空间&#xff1a;Context 之恶能容纳一个控件或布局控件 代表提内容控件&#xff1a;内容控件可以设置标题 Header 父类&#xff1a;HeaderContextControl。 条目控件&#xff1a;可以显示一列数据&#xf…

计算机网络复习-应用层

概述 传输层以及以下的层提供完整的通信服务&#xff0c;不需要管传输&#xff0c;只需要往上对接用户即可。应用层是面向用户的一层 定义应用间通信的规则 应用进程的报文类型 (请求报文、应答报文)报文的语法、格式应用进程发送数据的时机、规则 DNS详解 DNS&#xff1a…

js基础-数组-事件对象-日期-本地存储

一、大纲 一、获取元素位置 在JavaScript中&#xff0c;获取一个元素在页面上的位置可以通过多种方法实现。以下是一些常见的方法&#xff1a; getBoundingClientRect() getBoundingClientRect() 方法返回元素的大小及其相对于视口的位置。它提供了元素的left、top、right和bo…

[Linux][网络][高级IO][一][五种IO模型][同步通信][异步通信][非阻塞IO]详细讲解

目录 0.预备知识 && 思考问题1.五种IO模型0.形象理解五种模型1.阻塞IO2.非阻塞IO3.信号驱动IO4.多路转接/多路复用5.异步IO 2.高级IO重要概念1.同步通信 vs 异步通信2.阻塞 vs 非阻塞 3.非阻塞IO1.fcntl()2.实现SetNonBlock 0.预备知识 && 思考问题 网络通信本…

Poe是什么?怎样订阅Poe?

Poe&#xff08;全称“开放探索平台”&#xff0c;Platform for Open Exploration&#xff09;是一款由Quora开发的移动应用程序&#xff0c;于2022年12月推出。该应用程序内置建基于AI技术的聊天机器人&#xff0c;可供用户向机器人询问专业知识、食谱、日常生活&#xff0c;甚…

懒人网址导航源码v3.9

测试环境 宝塔Nginx -Tengine2.2.3的PHP5.6 MySQL5.6.44 为防止调试错误&#xff0c;建议使用测试环境运行的php与mysql版本 首先用phpMyAdmin导入数据库文件db/db.sql 如果导入不行&#xff0c;请直接复制数据库内容运行sql语句也可以 再修改config.php来进行数据库配置…

解决SpringBoot整合MyBatis和MyBatis-Plus,请求后不打印sql日志

问题发现 在整合springBootmyBatis时&#xff0c;发现请求不打印sql日志&#xff0c;示例代码如下&#xff1a; RestController public class MyController {AutowiredProductMapper productMapper;GetMapping("/test")public void test() {System.out.println(&qu…

使用Dockerfile配置Springboot应用服务发布Docker镜像-16

创建Docker镜像 springboot-docker模块 这个应用可以随便找一个即可&#xff0c;这里不做详细描述了。 pom.xml 依赖版本可参考 springbootSeries 模块中pom.xml文件中的版本定义 <dependencies><dependency><groupId>com.alibaba.cloud</groupId>…

[数据集][图像分类]杂草分类数据集17509张9类别

数据集格式&#xff1a;仅仅包含jpg图片&#xff0c;每个类别文件夹下面存放着对应图片 图片数量(jpg文件个数)&#xff1a;17509 分类类别数&#xff1a;9 类别名称:["chineseapple","lantana","negatives","parkinsonia","part…

Nginx - location中的匹配规则和动态Proxy

文章目录 官网location 规则详解动态Proxy使用多个 if 指令指定不同的 proxy_pass根据参数选择不同的 proxy_pass 官网 https://nginx.org/en/docs/http/ngx_http_core_module.html#location location 规则详解 Nginx的location指令工作原理如下&#xff1a; 位置匹配&#…

虚拟机有线已连接但无法上网—·可能性之一

背景 VMware虚拟机&#xff0c;搭建了三台Linux服务器&#xff0c;组成Hadoop集群&#xff0c;由于在Hadoop102上有一些经常与Mysql数据库交互的任务&#xff0c;需要经常打开运行&#xff0c;而Hadoop103和104则经常处于关闭状态&#xff0c;一段时间后再次启动集群时候&…

【go项目01_学习记录11】

操作数据库 1 文章列表2 删除文章 1 文章列表 &#xff08;1&#xff09;先保证文章已经有多篇&#xff0c;可以直接在数据库中添加&#xff0c;或者访问链接: localhost:3000/articles/create&#xff0c;增加几篇文章。 &#xff08;2&#xff09;之前设置好了articles.ind…

C语言 | Leetcode C语言题解之第87题扰乱字符串

题目&#xff1a; 题解&#xff1a; struct HashTable {int key;int val;UT_hash_handle hh; };void modifyHashTable(struct HashTable** hashTable, int x, int inc) {struct HashTable* tmp;HASH_FIND_INT(*hashTable, &x, tmp);if (tmp NULL) {tmp malloc(sizeof(st…

树莓派对FPGA板子上的流水灯程序的控制

文章目录 一 树莓派使用教程二 树莓派串口代码三 Verilog代码四 quartus引脚绑定五 运行效果总结 分别在DE2-115开发板和树莓派上编写串口通信程序&#xff0c; 实现树莓派串口指令对FPGA板子上的流水灯程序的控制&#xff0c;控制方式自定。 一 树莓派使用教程 参考&#xff…

第187题| 快速学会“阿贝尔定理”| 无穷级数(十五)|武忠祥老师每日一题

解题思路&#xff1a;这道题没有告诉我们是多少&#xff0c;没办法求出收敛半径&#xff0c;所以我们只能根据题目给的两个条件来解题&#xff08;选项代入法&#xff09;。 1.x-1&#xff0c;说明收敛的中心点是1&#xff0c;观察下列选项&#xff0c;显然答案在C和D之中。 …

Linux中的网络隔离功能 netns

Network Namespace&#xff08;netns&#xff09; 是Linux内核提供的一项实现网络隔离的功能&#xff0c;它能隔离多个不同的网络空间&#xff0c;并且各自拥有独立的网络协议栈。通过 namespace 可以隔离容器的进程 PID、文件系统挂载点、主机名等多种资源&#xff0c;它可以为…

基于门控的循环神经网络:LSTM

之前我们介绍了循环神经网络的原理以及实现。但是循环神经网络有一个问题&#xff0c;也就是长期依赖问题。我们之前的01序列预测案例中可以看到&#xff0c;当序列长度到达10以上之后错误就会增多&#xff0c;说明简单的RNN记忆容量较小&#xff0c;当长度更大时就不怎么适用了…

可重构柔性装配产线:为工业制造领域注入了新的活力

随着科技的飞速发展&#xff0c;智能制造正逐渐成为引领工业革新的重要力量。在这一浪潮中&#xff0c;可重构柔性装配产线以其独特的技术优势和创新理念&#xff0c;为工业制造领域注入了新的活力&#xff0c;开启了创新驱动的智能制造新篇章。 可重构柔性装配产线是基于富唯智…

2024年一些值得关注的边缘计算招投标!中国移动、中国联通、中国铁塔大单来了!...

1.大单来了&#xff01;中国移动湖北公司算力设备采购(移动边缘云四期扩容)招标公告&#xff0c;3079万&#xff01; 项目名称&#xff1a;中国移动湖北公司算力设备采购(移动边缘云四期扩容)招标公告 本招标项目为(中国移动湖北公司算力设备采购(移动边缘云四期扩容)&#xff…