tencent cloud

TDMQ for MQTT

Using a Client to Send Messages

PDF
Focus Mode
Font Size
Last updated: 2026-04-01 16:30:54
The MQTT publish/subscribe model initiates message communication through publishing. Publishing refers to the process where a client sends messages to a specific topic on the broker. The broker is responsible for receiving published messages and forwarding them to all clients subscribed to matching topics. The publishing feature serves as the core mechanism for devices or applications to report data upstream, send commands, and trigger events.

Publishing Principle

1. Establishing a connection: The client first establishes a TCP/IP connection with the MQTT broker and sends a CONNECT packet for authentication handshake. Upon success, a session is established.
2. Preparing a message: The client constructs a PUBLISH packet, that is, the message to be sent, including the topic (message destination), payload (message data), and control attributes (QoS level, retain flag, and so on).
3. Sending the message and an acknowledgment: The client sends the PUBLISH packet to the broker, containing all the message information described above. The broker replies to the publishing client with an acknowledgment packet (such as PUBACK/PUBREC) according to the QoS level specified in the packet, ensuring reliability for the sender.
4. Routing the message: Upon receiving the message, the broker looks up clients subscribed to that topic and forwards the message to them. For each subscriber, message delivery will be performed again according to the QoS level specified during subscription.

Quality of Service

Quality of Service (QoS) refers to the service quality of message transmission. Each message can have its QoS set individually during sending. It includes the following levels:
QoS Level
Workflow
Advantages
Disadvantages
Scenarios
QoS = 0
(At most once delivery)
The sender sends the message without requiring acknowledgment from the receiver.
The transmission speed is the fastest and the overhead is the lowest.
Messages may be lost in cases such as network failures or when the receiver is offline.
Non-critical data that can tolerate occasional loss, such as periodic sensor data (temperature, humidity), where a lost data point will soon be replaced by the next one.
QoS = 1
(At least once delivery)
1. The sender sends the message and retains a copy.
2. Upon receiving the message, the receiver must reply with a PUBACK (Publish Acknowledgment) packet.
3. The sender discards the message copy only after receiving the PUBACK.
4. If the sender does not receive PUBACK within a reasonable time, it resends the message.
Ensures that messages are not lost.
This may result in message duplication.
Guaranteed message delivery is required, and occasional duplication is acceptable. For example, control commands ("turning on/off lights") may still function correctly even if executed more than once.
QoS = 2
(Exactly once delivery)
1. PUBLISH: The sender sends the message and retains a copy.
2. PUBREC: Upon receipt, the receiver replies with a "received" acknowledgment. If the sender does not receive the PUBREC, it resends the PUBLISH.
3. PUBREL: Upon receiving PUBREC, the sender sends a "Publish Release" packet and can discard the message copy. It now only needs to await final confirmation.
4. PUBCOMP: Upon receiving the PUBREL, the receiver replies with a "publish complete" acknowledgment. Only then is the message delivered to the application. The sender concludes the process upon receiving the PUBCOMP. If either party fails to receive a response, it resends the previous packet.
Ensures that messages are not lost while guaranteeing non-duplication.
The speed is the slowest and the overhead is the highest.
For mission-critical operations that demand extremely high reliability and accuracy, such as billing systems, financial transactions, and critical state synchronization, any duplication or loss would lead to serious consequences.

Retained Message

When a message is published, you can set the retained parameter to true. The broker will then store the latest retained message for this topic.
When a new client subscribes to a matching topic, the broker immediately sends this latest retained message to it without waiting for its next publish. This is very useful for obtaining the latest device status.
For example, a temperature sensor publishes the current temperature every hour and sets it as a retained message. Any newly connected client subscribing to sensor/temperature will immediately receive the latest temperature without waiting for the next hour.

Last Will and Testament

Last Will and Testament (LWT) is not a direct publishing action, but a predefined message configured when the client connects. If the client disconnects unexpectedly (due to network failure or heartbeat timeout), the broker will automatically publish this LWT message to the specified topic on behalf of the client. It is commonly used to notify other clients that a device has gone offline abnormally.

Example of Sending Message Code


package com.tencent.tdmq.mqtt.example.paho.v5;

import java.nio.charset.StandardCharsets;
import java.util.List;
import org.eclipse.paho.mqttv5.client.IMqttToken;
import org.eclipse.paho.mqttv5.client.MqttCallback;
import org.eclipse.paho.mqttv5.client.MqttClient;
import org.eclipse.paho.mqttv5.client.MqttConnectionOptions;
import org.eclipse.paho.mqttv5.client.MqttDisconnectResponse;
import org.eclipse.paho.mqttv5.client.persist.MemoryPersistence;
import org.eclipse.paho.mqttv5.common.MqttException;
import org.eclipse.paho.mqttv5.common.MqttMessage;
import org.eclipse.paho.mqttv5.common.packet.MqttProperties;
import org.eclipse.paho.mqttv5.common.packet.UserProperty;

public class PublisherQuickStart {

public static void main(String[] args) throws MqttException, InterruptedException {
// Get the access point from the MQTT console:
// For users implementing VPC connectivity via Private Link, use the private network access point.
// For users accessing over the public network, ensure the public network security policy permits access, and the machine running the program has public network connectivity.
String serverUri = "tcp://mqtt-xxx.mqtt.tencenttdmq.com:1883";

// A valid client identifier contains digits 0-9, lowercase letters a-z, and uppercase letters A-Z, with a total length of 1-23 characters
// See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901059.
String clientId = "PublisherQuickStart";

// In the console, on the Authentication tab, create an account and copy the username and password.
String username = "user0";
String password = "secret0";

// MQTT topic
String topicName = "home/test";

MqttClient client = new MqttClient(serverUri, clientId, new MemoryPersistence());
client.setTimeToWait(3000);
MqttConnectionOptions options = new MqttConnectionOptions();
options.setUserName(username);
options.setPassword(password.getBytes(StandardCharsets.UTF_8));
options.setCleanStart(true);
options.setAutomaticReconnect(true);

client.setCallback(new MqttCallback() {
@Override
public void disconnected(MqttDisconnectResponse response) {
System.out.println("Disconnected: " + response.getReasonString());
}

@Override
public void mqttErrorOccurred(MqttException e) {
e.printStackTrace();
}

@Override
public void messageArrived(String topic, MqttMessage message) {
}

@Override
public void deliveryComplete(IMqttToken token) {
System.out.println("Delivery completed: packet-id=" + token.getMessageId() +
", reason-code=" + token.getResponse().getReasonCodes()[0]);

List<UserProperty> userProperties = token.getResponseProperties().getUserProperties();
printUserProperties(userProperties);
}

@Override
public void connectComplete(boolean reconnect, String serverURI) {
System.out.println(reconnect ? "Reconnected" : "Connected" + " to " + serverURI);
}

@Override
public void authPacketArrived(int i, MqttProperties properties) {
System.out.println("Received auth packet with id: " + i);
}
});

client.connect(options);

int total = 16;
for (int i = 0; i < total; i++) {
String msg = "Hello MQTT " + i;
MqttMessage message = new MqttMessage(msg.getBytes(StandardCharsets.UTF_8));
message.setQos(1);
System.out.printf("Prepare to publish message %d%n", i);
client.publish(topicName, message);
System.out.printf("Published message %d%n", i);
}

client.disconnect();

client.close();
}

static void printUserProperties(List<UserProperty> userProperties) {
if (null != userProperties) {
for (UserProperty userProperty : userProperties) {
System.out.printf("User property: %s = %s%n", userProperty.getKey(), userProperty.getValue());
}
}
}
}

Help and Support

Was this page helpful?

Help us improve! Rate your documentation experience in 5 mins.

Feedback