Einfacher CoAP-Client
Erstellen einer Anwendung, die mit einem CoAP-Server kommuniziert.

„Einfacher CoAP-Client“ zeigt, wie man eine minimalistische CoAP-Client-Anwendung erstellt, um CoAP-Nachrichten zu senden und zu empfangen.
Ausführen des Beispiels
Sie können das Beispiel wie folgt ausführen:
- Qt Creator
Öffnen Sie den Modus „ Welcome “ und wählen Sie das Beispiel unter „ Examples “ aus. Weitere Informationen finden Sie unter Qt Creator: Tutorial: Erstellen und Ausführen.
- Qt Extension for Visual Studio Code
Führen Sie den Befehl „ Qt: Open Qt examples “ über „ Command Palette “ aus und wählen Sie das Beispiel aus der Liste aus. Weitere Informationen finden Sie unter Qt Extension for Visual Studio Code: Tutorial: Erstellen und Ausführen.
Einrichten eines CoAP-Servers
Um die Anwendung nutzen zu können, müssen Sie einen CoAP-Server angeben. Sie haben folgende Möglichkeiten:
- Verwenden Sie den CoAP-Testserver unter
coap://coap.me. - Erstellen Sie einen CoAP-Server mit libcoap, FreeCoAP oder einer anderen CoAP-Server-Implementierung.
- Verwenden Sie den Californium-Plugtest-Server, der die meisten CoAP-Funktionen unterstützt. Sie können ihn manuell erstellen oder ein fertiges Docker-Image verwenden, das den Plugtest-Server erstellt und startet. Die Schritte zur Verwendung des Docker-basierten Servers werden im Folgenden beschrieben.
Verwendung des Docker-basierten Test-Servers
Der folgende Befehl ruft den Docker-Container für den CoAP-Server vom Docker Hub ab und startet ihn:
docker run --name coap-test-server -d --rm -p 5683:5683/udp -p 5684:5684/udp tqtc/coap-californium-test-server:3.8.0Um die IP-Adresse des Docker-Containers zu ermitteln, rufen Sie zunächst die Container-ID ab, indem Sie den Befehl „ docker ps “ ausführen. Die Ausgabe sieht in etwa so aus:
$ docker ps
CONTAINER ID IMAGE
5e46502df88f tqtc/coap-californium-test-server:3.8.0Anschließend können Sie die IP-Adresse mit dem folgenden Befehl abrufen:
docker inspect <container_id> | grep IPAddressBeispiel:
$ docker inspect 5e46502df88f | grep IPAddress
...
"IPAddress": "172.17.0.2",
...Der CoAP-Testserver ist über die abgerufene IP-Adresse auf den Ports 5683 (ungesichert) und 5684 (gesichert) erreichbar.
Um den Docker-Container nach der Nutzung zu beenden, verwenden Sie den folgenden Befehl:
docker stop <container_id>Die hier angegebene „ <container_id> “ entspricht der durch den Befehl „ docker ps “ ermittelten ID.
Erstellen eines Clients
Der erste Schritt besteht darin, mithilfe der Klasse „ QCoapClient “ einen CoAP-Client zu erstellen. Anschließend müssen wir dessen Signale verbinden, um benachrichtigt zu werden, wenn eine CoAP-Antwort empfangen wird oder eine Anfrage fehlgeschlagen ist:
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);
...Anfragen senden
Wir verwenden die Klasse ` QCoapRequest `, um CoAP-Anfragen zu erstellen. Diese Klasse stellt Methoden zum Erstellen von CoAP-Frames bereit.
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);
...In diesem Beispiel legen wir die URL sowie den Nachrichtentyp fest und fügen der Anfrage Optionen hinzu. Es ist auch möglich, die Nutzdaten, die Nachrichten-ID, das Token usw. festzulegen, aber wir verwenden hier die Standardwerte. Beachten Sie, dass die Nachrichten-ID und das Token standardmäßig zufällig generiert werden.
Je nach gewählter Anfragemethode senden wir eine „ GET “-Anfrage, eine „ PUT “-Anfrage, eine „ POST “-Anfrage oder eine „ DELETE “-Anfrage an den Server:
...
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;
}
...Bei PUT - und POST -Anfragen fügen wir außerdem m_currentData als Nutzdaten für die Anfrage hinzu.
Um den Inhalt des Servers zu durchsuchen und die darauf verfügbaren Ressourcen zu ermitteln, wird eine Erkundungsanfrage verwendet:
void MainWindow::on_discoverButton_clicked()
{
...
QCoapResourceDiscoveryReply *discoverReply =
m_client->discover(url, ui->discoveryPathEdit->text());
if (discoverReply) {
connect(discoverReply, &QCoapResourceDiscoveryReply::discovered,
this, &MainWindow::onDiscovered);
...Hinweis: Anstelle der Klasse „ QCoapReply “ verwenden wir die Klasse „ QCoapResourceDiscoveryReply “, um die Antwort auf eine Discovery-Anfrage zu erhalten. Diese verfügt über das Signal „ QCoapResourceDiscoveryReply::discovered “, das die Liste der entdeckten QCoapResources zurückgibt.
Wenn auf dem Server beobachtbare Ressourcen vorhanden sind (d. h., sie haben den Ressourcentyp „ obs “), können wir Updates zu dieser Ressource abonnieren, indem wir eine Beobachtungsanfrage ausführen:
void MainWindow::on_observeButton_clicked()
{
...
QCoapReply *observeReply = m_client->observe(url);
...
connect(observeReply, &QCoapReply::notified, this, &MainWindow::onNotified);
...Der Client kann die Beobachtung der Ressource beenden, indem er das Signal „ clicked() “ des „ cancelObserveButton “ verarbeitet:
...
connect(ui->cancelObserveButton, &QPushButton::clicked, this, [this, url]() {
m_client->cancelObserve(url);
ui->cancelObserveButton->setEnabled(false);
});Die vom Server kommenden Antworten werden in der Benutzeroberfläche angezeigt:
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;
}Dateien:
© 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.