Qt CoAP 概述#

深入了解 CoAP 协议和 Qt CoAP 模块。

受限应用协议(CoAP)是一种专为受限网络(如微控制器等)之间的 M2M 数据交换而设计的物联网协议。

CoAP 的交互模式类似于 HTTP 的客户端/服务器模型,但与 HTTP 不同,它使用基于数据报的无连接传输,如 UDP,这导致非常低的开销,并允许使用 UDP 广播和多播进行寻址。同时,它还提供了轻量级的可靠性和安全机制。

Qt CoAP 实现了 CoAP 的客户端功能。默认情况下,传输层使用 QUdpSocket 和 QDtls 进行安全通信。可以通过实现 QCoapConnection 接口使用替代传输。

消息模型#

CoAP 消息模型基于端点之间的消息交换:客户端向服务器发送请求;服务器发送响应。客户端可以获取资源(GET)、设置资源(PUT)、创建资源(POST)和删除资源(DELETE)。它们还可以通过发送发现请求来在服务器上查找资源,或在本地网络中,通过发送多播发现请求。还可以通过观察请求订阅资源。

通过标记消息为确认(CON)实现传输的可靠性。可确认消息仅在默认超时和重传之间的指数退避期间重新传输,直到接收方发送确认(ACK)消息。如果接收方无法处理可确认消息,则回复重置(RST)消息而不是确认。

不需要可靠传输的消息可以作为一个非确认(NON)消息发送。

使用 Qt CoAP API#

客户端与 CoAP 服务器的通信是通过 QCoapClient 类进行的。它包含发送不同 CoAP 请求的方法以及当收到的响应触发时发出的信号。使用 QCoapRequest 类来创建 CoAP 请求。来自服务器的响应在一个 QCoapReply 对象中返回。例如

QCoapClient *client = new QCoapClient();
connect(client, &QCoapClient::finished, this, &MyClass::onFinished);
connect(client, &QCoapClient::error, this, &MyClass::onError);

QCoapRequest request(QUrl("coap://127.0.0.1/test"), QCoapMessage::Confirmable);
client->get(request);
client->put(request, QByteArray("payload"));

支持的功能#

资源发现#

CoAP 发现请求用于查询端点或整个网络中可用的资源。这对于没有人类参与的 M2M 应用程序非常重要。例如,在家庭或建筑自动化中,需要本地客户端和服务器在无需人类干预的情况下相互发现和交互。资源发现使客户端能够在网络中了解到可用的端点。

Qt CoAP 支持对单个端点和多播组的发现请求。例如,对 /.well-known/core 的发现请求,这是默认的资源发现入口点,可能会返回类似

RES: 2.05 Content
</sensors/temp>;rt="temperature-c";if="sensor";obs,
</sensors/light>;rt="light-lux";if="sensor",
</firmware/v2.1>;rt="firmware";sz=262144

表示该网络中有温度和光传感器资源以及固件资源。回复以 CoRE 链接格式 表示。

使用专门的 QCoapResourceDiscoveryReply 类来获取发现回复

// This will make a multicast discovery request to the CoAP IPv4 multicast group.
QCoapResourceDiscoveryReply *discoverReply = client->discover();
connect(discoverReply, &QCoapResourceDiscoveryReply::discovered, this, &MyClass::onDiscovered);

discovered 将返回在网络中找到的 CoAP 资源列表。

资源观察#

使用观察请求来接收资源的自动服务器通知。客户端通过向资源发送观察请求成为可观察资源的观察者。例如,上述示例中的温度传感器是可观察的,因为它具有 obs 属性。因此,客户端可以通过向其发送观察请求来订阅温度更新。

以下示例代码展示了如何使用 Qt CoAP 发送观察请求

QCoapReply *reply = client->observe(QUrl("127.0.0.1/temp"));
connect(reply, &QCoapReply::notified, this, &MyClass::onNotified);

对于观察请求特别地,您可以使用 notified 信号来处理来自 CoAP 服务器的通知。

分块传输#

由于 CoAP 基于 UDP 等数据报传输,对于单一的 CoAP 数据报可以传输而不会引起碎片化问题的资源表示的大小存在限制。Qt CoAP 支持分块传输,用于资源表示大于单个 CoAP 数据报有效负载可以舒适地传输的情况。

安全性#

以下安全性模式被定义用于 CoAP

  • 预共享密钥 - 在此模式下,客户端必须将其身份和预共享密钥发送到服务器。

  • 原始公钥 - 客户端有一对非对称密钥,没有证书(原始公钥)。客户端还有一个由公钥计算得出的身份,以及它可以进行通信的节点的身份列表。Qt CoAP 尚未实现此模式。

  • 证书 - 客户端有一对带有由某些常用信任根签名的 X.509 证书的非对称密钥。

由于 CoAP 被设计成基于 UDP 的协议,Qt CoAP 模块通过在 UDP 上实现基于数据报 TLS(DTLS)来执行安全性。然而,如上所述,可以提供具有其他安全类型的自定义传输。

为了保护 CoAP 客户端,在创建客户端时应指定支持的安全性模式之一

QCoapClient *client = new QCoapClient(this, QtCoap::PreSharedKey);

使用 QCoapSecurityConfiguration 类来指定安全参数。例如,在预共享密钥模式下,可以使用以下示例代码

QCoapSecurityConfiguration config;
config.setPreSharedKey("secretPSK");
config.setIdentity("Client_identity");
client->setSecurityConfiguration(config);

以及在证书模式下

QCoapClient *client = new QCoapClient(this, QtCoap::Certificate);
QList<QSslCertificate> localCertificates, caCertificates;
QCoapPrivateKey key;
// Initialize the key and certificates
QCoapSecurityConfiguration config;
config.setLocalCertificateChain(localCertificates);
config.setCaCertificates(caCertificates)
config.setPrivateKey(key);
client->setSecurityConfiguration(config);