本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
coreMQTT 代理连接共享演示
介绍
CoreMQTT 连接共享演示项目向您展示了如何使用多线程应用程序建立与Amazon借助客户端和服务器之间的双向身份验证,使用 TLS 代理。本演示使用基于 MBedTLS 的传输接口实现来建立服务器和客户端身份验证的 TLS 连接,并在QoS 1
要设置和运行 FreeRTOS 演示,请按照中的步骤操作入门.
本演示使用线程安全队列来保存命令以与 MQTT API 进行交互。本演示中有两个任务需要注意。
-
MQTT Agent(主)任务处理命令队列中的命令,而其他任务将这些命令排入队列。此任务进入循环,在循环期间处理来自命令队列的命令。如果收到终止命令,此任务将打破循环。
-
演示子酒吧任务会创建对 MQTT 主题的订阅,然后创建发布操作并将其推送到命令队列。然后,这些发布操作由 MQTT 代理任务运行。demo subpub 任务等待发布完成(通过执行命令完成回调来表示),然后在开始下一次发布之前进入短暂的延迟。此任务展示了应用程序任务将如何使用 CoreMQTT 代理 API 的示例。
对于传入的发布消息,CoreMQTT 代理调用单个回调函数。此演示还包括一个订阅管理器,该管理器允许任务指定回调函数,以便针对他们已订阅的主题的传入发布消息调用。此演示中代理的传入发布回调调函数会调用订阅管理器来粉丝发布到已注册订阅的任何任务。
本演示使用 TLS 连接和相互身份验证来连接到Amazon. 如果在演示期间网络意外断开连接,则客户端将尝试使用指数退避逻辑重新连接。如果客户成功重新连接,但经纪商无法恢复之前的会话,则客户将重新订阅与上次会话相同的主题。
单线程 vs 多线程
有两种 CoreMQTT 使用模式:单线程和多线程(多任务处理)。单线程模型仅从一个线程中使用 CoreMQTT 库,并且要求您在 MQTT 库中重复进行显式调用。相反,多线程使用案例可以在代理(或守护程序)任务中的后台运行 MQTT 协议,如此处记录的演示中所示。当你在代理任务中运行 MQTT 协议时,你不必明确管理任何 MQTT 状态或调用MQTT_ProcessLoop
API 函数。此外,当您使用代理任务时,多个应用程序任务可以共享单个 MQTT 连接,而无需同步原语(例如互斥锁)。
源代码
演示源文件被命名为mqtt_agent_task.c
和simple_sub_pub_demo.c
并且可以在
目录和GitHubfreertos
/demos/coreMQTT_Agent/
功能
此演示至少创建两个任务:一个处理 MQTT API 调用请求的主任务,以及创建这些请求的可配置数量的子任务。在本演示中,主要任务创建子任务,调用处理循环,然后进行清理。主要任务创建与代理的单个 MQTT 连接,该连接在子任务之间共享。子任务与经纪商创建 MQTT 订阅,然后向其发布消息。每个子任务都使用独特的主题进行发布。
主要任务
主要的应用任务,runcoreMqtTagentDemo
命令
当你调用 CoreMQTT 代理 API 时,它会创建一个命令发送到座席任务的队列,该命令将在MQTTAgent_CommandLoop()
. 在创建命令时,可能会传递可选的完成回调函数和上下文参数。相应的命令完成后,完成回调将与传递的上下文和由于该命令创建的任何返回值一起调用。完成回调的签名如下:
typedef void (* MQTTAgentCommandCallback_t )( void * pCmdCallbackContext, MQTTAgentReturnInfo_t * pReturnInfo );
命令完成上下文是用户定义的;对于本演示,它是:结构 MQttagent 命令上下文
在以下情况下,命令视为已完
-
使用 QoS > 0 订阅、取消订阅和发布:收到相应的确认数据包后。
-
所有其他操作:一旦调用了相应的 CoreMQTT API。
该命令使用的任何结构(包括发布信息、订阅信息和完成上下文)都必须保持在范围内,直到命令完成。在调用完成回调之前,调用任务不得重复使用任何命令的结构。请注意,由于完成回调是由 MQTT Agent 调用的,因此它将与代理任务的线程上下文一起运行,而不是创建命令的任务。进程间通信机制(例如任务通知或队列)可用于发出命令完成的调用任务的信号。
运行命令循环
命令在中持续处理MQTTAgent_CommandLoop()
. 如果没有要处理的命令,循环将等待最多MQTT_AGENT_MAX_EVENT_QUEUE_WAIT_TIME
要添加到队列中的一个,如果没有添加任何命令,它将运行MQTT_ProcessLoop()
. 这可以确保管理 MQTT Keep-Alive,而且即使队列中没有命令,也可以接收任何传入的发布。
由于以下原因,命令循环函数将返回:
-
除此之外,命令返回任何状态码
MQTTSuccess
. 错误状态由命令循环返回,因此你可以决定如何处理它。在本演示中,重新建立了 TCP 连接,并尝试重新连接。如果有任何错误,可能会在后台重新连接,而无需使用 MQTT 的其他任务进行任何干预。 -
断开连接命令(来自
MQTTAgent_Disconnect
) 已处理。命令循环退出以便 TCP 可以断开连接。 -
终止命令(来自
MQTTAgent_Terminate
) 已处理。此命令还将队列中或等待确认包的任何命令标记为错误,返回代码为MQTTRecvFailed
.
订阅管理器
由于该演示使用多个主题,因此订阅管理器是将订阅主题与唯一的回调或任务关联起来的便捷方式。本演示中的订阅管理器是单线程的,因此不应该同时由多个任务使用。在此演示中,只能从传递给 MQTT 代理的回调函数调用订阅管理器函数,并且仅在代理任务的线程上下文中运行。
简单的订阅-发布任务
的每个实例prvSimpleSubscribbe 发布任务