Cliente CoAP simple
Creación de una aplicación que se comunica con un servidor CoAP.

Simple CoAP Client demuestra cómo crear una aplicación cliente CoAP minimalista para enviar y recibir mensajes CoAP.
Ejecutar el ejemplo
Para ejecutar el ejemplo desde Qt Creatorabra el modo Welcome y seleccione el ejemplo de Examples. Para más información, consulta Qt Creator: Tutorial: Construir y ejecutar.
Configuración de un servidor CoAP
Para utilizar la aplicación, es necesario especificar un servidor CoAP. Tiene las siguientes opciones:
- Utilizar el servidor CoAP de prueba ubicado en
coap://coap.me. - Crear un servidor CoAP utilizando libcoap, FreeCoAP o cualquier otra implementación de servidor CoAP.
- Utilizar el servidor Californium plugtest, que soporta la mayoría de las características CoAP. Puedes construirlo manualmente o utilizar una imagen Docker preparada, que construye e inicia el servidor plugtest. A continuación se describen los pasos para utilizar el servidor basado en Docker.
Uso del servidor de pruebas basado en Docker
El siguiente comando extrae el contenedor docker para el servidor CoAP del Docker Hub y lo inicia:
docker run --name coap-test-server -d --rm -p 5683:5683/udp -p 5684:5684/udp tqtc/coap-californium-test-server:3.8.0
Para averiguar la dirección IP del contenedor docker, primero recupera el ID del contenedor ejecutando docker ps, que mostrará algo como:
$ docker ps CONTAINER ID IMAGE 5e46502df88f tqtc/coap-californium-test-server:3.8.0
A continuación, puede obtener la dirección IP con el siguiente comando:
docker inspect <container_id> | grep IPAddress
Por ejemplo:
$ docker inspect 5e46502df88f | grep IPAddress ... "IPAddress": "172.17.0.2", ...
El servidor de prueba CoAP será accesible por la dirección IP recuperada en los puertos 5683 (no seguro) y 5684 (seguro).
Para terminar el contenedor docker después de su uso, utilice el siguiente comando:
docker stop <container_id>
El <container_id> aquí es el mismo que el recuperado por el comando docker ps.
Creación de un cliente
El primer paso es crear un cliente CoAP utilizando la clase QCoapClient. Luego necesitamos conectar sus señales, para ser notificados cuando una respuesta CoAP es recibida o una petición ha fallado:
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { m_client = new QCoapClient(QtCoap::SecurityMode::NoSecurity, this); connect(m_client, &QCoapClient::finished, this, &MainWindow::onFinished); connect(m_client, &QCoapClient::error, this, &MainWindow::onError); ...
Envío de peticiones
Usamos la clase QCoapRequest para crear peticiones CoAP. Esta clase proporciona métodos para construir tramas CoAP.
void MainWindow::on_runButton_clicked() { const auto msgType = ui->msgTypeCheckBox->isChecked() ? QCoapMessage::Type::Confirmable : QCoapMessage::Type::NonConfirmable; QUrl url; url.setHost(tryToResolveHostName(ui->hostComboBox->currentText())); url.setPort(ui->portSpinBox->value()); url.setPath(ui->resourceComboBox->currentText()); QCoapRequest request(url, msgType); for (const auto &option : std::as_const(m_options)) request.addOption(option); ...
En este ejemplo, establecemos la URL, así como el tipo de mensaje y añadimos opciones a la petición. También es posible establecer la carga útil, el ID del mensaje, el token, etc., pero aquí utilizaremos los valores por defecto. Tenga en cuenta que, por defecto, el ID del mensaje y el token se generan aleatoriamente.
Basándonos en el método de petición seleccionado, enviamos una petición GET, PUT, POST o DELETE al servidor:
...
switch (method) {
case QtCoap::Method::Get:
m_client->get(request);
break;
case QtCoap::Method::Put:
m_client->put(request, m_currentData);
break;
case QtCoap::Method::Post:
m_client->post(request, m_currentData);
break;
case QtCoap::Method::Delete:
m_client->deleteResource(request);
break;
default:
break;
}
...Para las peticiones PUT y POST también añadimos m_currentData como carga útil de la petición.
Para navegar por el contenido del servidor y descubrir los recursos disponibles en él, se utiliza una petición de descubrimiento:
void MainWindow::on_discoverButton_clicked() { ... QCoapResourceDiscoveryReply *discoverReply = m_client->discover(url, ui->discoveryPathEdit->text()); if (discoverReply) { connect(discoverReply, &QCoapResourceDiscoveryReply::discovered, this, &MainWindow::onDiscovered); ...
Nota: En lugar de la clase QCoapReply, utilizamos la clase QCoapResourceDiscoveryReply para guardar la respuesta de una petición de descubrimiento. Tiene la señal QCoapResourceDiscoveryReply::discovered, que devuelve la lista de QCoapResources que han sido descubiertos.
Si hay recursos observables en el servidor (lo que significa que tienen el tipo de recurso obs), podemos suscribirnos a las actualizaciones de ese recurso ejecutando una petición observe:
void MainWindow::on_observeButton_clicked() { ... QCoapReply *observeReply = m_client->observe(url); ... connect(observeReply, &QCoapReply::notified, this, &MainWindow::onNotified); ...
El cliente puede darse de baja de la observación del recurso manejando la señal clicked() del cancelObserveButton:
...
connect(ui->cancelObserveButton, &QPushButton::clicked, this, [this, url]() {
m_client->cancelObserve(url);
ui->cancelObserveButton->setEnabled(false);
});Las respuestas procedentes del servidor se muestran en la interfaz de usuario:
void MainWindow::addMessage(const QString &message, bool isError) { const QString content = "--------------- %1 ---------------\n%2\n\n"_L1 .arg(QDateTime::currentDateTime().toString(), message); ui->textEdit->setTextColor(isError ? Qt::red : Qt::black); ui->textEdit->insertPlainText(content); ui->textEdit->ensureCursorVisible(); } void MainWindow::onFinished(QCoapReply *reply) { if (reply->errorReceived() == QtCoap::Error::Ok) addMessage(reply->message().payload()); } static QString errorMessage(QtCoap::Error errorCode) { const auto error = QMetaEnum::fromType<QtCoap::Error>().valueToKey(static_cast<int>(errorCode)); return MainWindow::tr("Request failed with error: %1\n").arg(error); } void MainWindow::onError(QCoapReply *reply, QtCoap::Error error) { const auto errorCode = reply ? reply->errorReceived() : error; addMessage(errorMessage(errorCode), true); } void MainWindow::onDiscovered(QCoapResourceDiscoveryReply *reply, QList<QCoapResource> resources) { if (reply->errorReceived() != QtCoap::Error::Ok) return; QString message; for (const auto &resource : std::as_const(resources)) { ui->resourceComboBox->addItem(resource.path()); message += tr("Discovered resource: \"%1\" on path %2\n") .arg(resource.title(), resource.path()); } addMessage(message); } void MainWindow::onNotified(QCoapReply *reply, const QCoapMessage &message) { if (reply->errorReceived() == QtCoap::Error::Ok) { addMessage(tr("Received observe notification with payload: %1") .arg(QString::fromUtf8(message.payload()))); } } static QString tryToResolveHostName(const QString hostName) { const auto hostInfo = QHostInfo::fromName(hostName); if (!hostInfo.addresses().empty()) return hostInfo.addresses().first().toString(); return hostName; }
Archivos:
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.