之前使用过Eclipse Paho附上文章链接Eclipse Paho 实现Android推送
讲述一下两者的使用感受
功能 | FuseSource | Eclipse Paho |
---|---|---|
MQTT 3.1.1 | 支持 | 支持 |
SSL | 支持 | 支持 |
TLS | 不支持 | 支持 |
自动重连 | 支持 | 支持 |
Blocking API | 支持 | 不支持 |
在线API | 没有 | 有 |
连续publish | 支持 | 不支持 |
使用 | 方便 | 麻烦 |
之前一直都是使用Eclipse Paho, 后来发现一个Bug, 每publish一次连接都会断开大约一秒后自动重连, 不能连续不间断的发送数据, 被迫无奈之下转向新的阵营(FuseSource), 经测试可以连续不间断发送数据。
MQTT是机器对机器(M2M)/“物联网”连接协议。它被设计成一个非常轻量级的发布/订阅消息传输。对于需要较小代码空间和/或网络带宽较高的远程位置进行连接非常有用。
mqtt-client为MQTT提供了ASL 2.0许可的API。它负责自动重新连接到您的MQTT服务器,并在出现任何网络故障时恢复您的客户端会话。应用程序可以使用blocking API风格、 一个futures based API 或callback/continuations passingAPI风格。
从Maven使用
将以下内容添加到您的maven pom.xml文件中
org.fusesource.mqtt-client
mqtt-client
1.12
从Gradle使用
将以下内容添加到您的gradle文件中
implementation 'org.fusesource.mqtt-client:mqtt-client:1.12'
从任何其他构建系统使用
下载 uber jar文件 并将其添加到您的项目, uber包含mqtt客户端从其他项目所依赖的所有精简依赖项。
配置MQTT连接
blocking, future, 和callback APIs都共享相同的连接设置。您可以创建MQTT该类的新实例,并使用连接和套接字相关选项对其进行配置。在尝试连接之前调用该方法(setHost)。
MQTT mqtt = new MQTT();
mqtt.setHost("localhost", 1883);
// or
mqtt.setHost("tcp://localhost:1883");
配置MQTT选项
-
setClientId
:用于设置会话的客户端ID。这是MQTT服务器用来识别setCleanSession(false);正在使用的会话的内容。该ID必须为23个字符或更少。默认为自动生成的ID(基于您的套接字地址,端口和时间戳)。 -
setCleanSession
:如果希望MQTT服务器在客户端会话中保留主题订阅和确认位置,则设置为false。默认为true。 -
setKeepAlive
:在几秒钟内配置Keep Alive计时器。定义从客户端收到的消息之间的最大时间间隔。它使服务器能够检测到到客户端的网络连接已经丢失,而无需等待较长的TCP / IP超时。 -
setUserName
:设置用于对服务器进行身份验证的用户名。 -
setPassword
:设置用于对服务器进行身份验证的密码。 -
setWillTopic
:如果设置,服务器将在客户端发生意外断开连接时将客户端的Will消息发布到指定主题。 -
setWillMessage
:将发送的意愿消息。默认为零长度的消息。 -
setWillQos
:设置用于Will消息的服务质量。默认为QoS.AT_MOST_ONCE。 -
setWillRetain
:如果您希望使用保留选项发布遗嘱,请设置为true。 -
setVersion
:设置为“3.1.1”以使用MQTT版本3.1.1。否则默认为3.1协议版本。
配置重新连接
如果发生网络错误,连接将自动重新连接并重新建立消息传递会话。您可以控制尝试重新连接的频率,并使用以下方法定义重新连接尝试的最大次数:
-
setConnectAttemptsMax
:在客户端首次尝试连接到服务器时,在将错误报告给客户端之前,尝试重新连接的最大次数。设置为-1以使用无限尝试。默认为-1。 -
setReconnectAttemptsMax
:在先前建立了服务器连接之后,在将错误报告给客户端之前,重新连接尝试的最大次数。设置为-1以使用无限尝试。默认为-1。 -
setReconnectDelay
:在第一次重新连接尝试之前,等待多长时间ms。默认为10。 -
setReconnectDelayMax
:重新连接尝试之间等待的最长时间(以毫秒为单位)。默认为30,000。 -
setReconnectBackOffMultiplier
:在重新连接尝试之间使用指数退避。设置为1以禁用指数退避。默认为2。
配置套接字选项
您可以使用以下方法调整某些套接字选项:
-
setReceiveBufferSize
:设置内部套接字接收缓冲区的大小。
默认为65536(64k) -
setSendBufferSize
:设置内部套接字发送缓冲区的大小。
默认为65536(64k) -
setTrafficClass
:为从传输器发送的数据包设置IP标头中的流量类别或服务类型八位字节。默认为8这意味着流量应该针对吞吐量进行优化。
节流连接
如果您想要降低连接的读取或写入速度,请使用以下方法:
-
setMaxReadRate
:设置此传输将在每秒接收数据的最大字节数。此设置限制读取,以便不超过速率。默认为0,禁用限制。 -
setMaxWriteRate
:设置此传输器将在其每秒发送数据的最大字节数。此设置会限制写入操作,以便不会超出速率。默认为0,禁用限制。
使用SSL连接
如果要通过SSL / TLS而不是TCP进行连接,请为host
字段使用“ssl://”或“tls://”URI前缀而不是“tcp://” 。用于更细粒度地控制使用哪种算法。支持的协议值是:
-
ssl://
- 使用SSL算法的JVM默认版本。 -
sslv*://
- 使用特定的SSL版本,其中*
是您的JVM支持的版本。例:sslv3
-
tls://
- 使用JVM默认版本的TLS算法。 -
tlsv*://
- 在*
您的JVM支持的版本中使用特定的TLS版本。例:tlsv1.1
SSLContext
除非使用setSslContext
方法配置MQTT实例,否则客户端将使用通过JVM系统属性配置 的默认JVM 。
SSL连接对内部线程池执行阻塞操作,除非您调用setBlockingExecutor
方法来配置它们将使用的执行程序。
选择调度队列
一个HawtDispatch调度队列来同步访问连接。如果未通过该setDispatchQueue
方法配置显式队列,则将为该连接创建一个新队列。如果您希望多个连接共享同一队列进行同步,那么设置显式队列可能会很方便。
使用BlockingAPI
该MQTT.connectBlocking
方法建立连接并为您提供与阻塞API的连接。
BlockingConnection connection = mqtt.blockingConnection();
connection.connect();
使用以下publish
方法将消息发布到主题:
connection.publish("foo", "Hello".getBytes(), QoS.AT_LEAST_ONCE, false);
您可以使用该subscribe
方法订阅多个主题:
Topic[] topics = {new Topic("foo", QoS.AT_LEAST_ONCE)};
byte[] qoses = connection.subscribe(topics);
然后使用receive
和ack
方法接收并确认消息的消耗:
Message message = connection.receive();
System.out.println(message.getTopic());
byte[] payload = message.getPayload();
// process the message then:
message.ack();
最后断开:
connection.disconnect();
使用FutureAPI
该MQTT.connectFuture
方法建立连接并为您提供与期货样式API的连接。所有针对连接的操作都是非阻塞的,并通过Future返回结果。
FutureConnection connection = mqtt.futureConnection();
Future f1 = connection.connect();
f1.await();
Future f2 = connection.subscribe(new Topic[]{new Topic(utf8("foo"), QoS.AT_LEAST_ONCE)});
byte[] qoses = f2.await();
// We can start future receive..
Future receive = connection.receive();
// send the message..
Future f3 = connection.publish("foo", "Hello".getBytes(), QoS.AT_LEAST_ONCE, false);
// Then the receive will get the message.
Message message = receive.await();
message.ack();
Future f4 = connection.disconnect();
f4.await();
使用基于回调/继续传递的API
该MQTT.connectCallback
方法建立一个连接并为您提供与回调风格API的连接。这是使用API风格最复杂的,但可以提供最佳性能。未来和阻塞API使用封面下的回调API。连接上的所有操作都是非阻塞的,操作的结果将传递给您实现的回调接口。
例:
final CallbackConnection connection = mqtt.callbackConnection();
connection.listener(new Listener() {
public void onDisconnected() {
}
public void onConnected() {
}
public void onPublish(UTF8Buffer topic, Buffer payload, Runnable ack) {
// You can now process a received message from a topic.
// Once process execute the ack runnable.
ack.run();
}
public void onFailure(Throwable value) {
connection.close(null); // a connection failure occured.
}
})
connection.connect(new Callback() {
public void onFailure(Throwable value) {
result.failure(value); // If we could not connect to the server.
}
// Once we connect..
public void onSuccess(Void v) {
// Subscribe to a topic
Topic[] topics = {new Topic("foo", QoS.AT_LEAST_ONCE)};
connection.subscribe(topics, new Callback() {
public void onSuccess(byte[] qoses) {
// The result of the subcribe request.
}
public void onFailure(Throwable value) {
connection.close(null); // subscribe failed.
}
});
// Send a message to a topic
connection.publish("foo", "Hello".getBytes(), QoS.AT_LEAST_ONCE, false, new Callback() {
public void onSuccess(Void v) {
// the pubish operation completed successfully.
}
public void onFailure(Throwable value) {
connection.close(null); // publish failed.
}
});
// To disconnect..
connection.disconnect(new Callback() {
public void onSuccess(Void v) {
// called once the connection is disconnected.
}
public void onFailure(Throwable value) {
// Disconnects never fail.
}
});
}
});
每个连接都有一个HawtDispatch调度队列,它用于处理套接字的IO事件。派发队列是一个执行器,提供IO的串行执行和处理事件,并用于确保连接的同步访问。
回调将执行与连接相关联的调度队列,因此可以安全地使用来自回调的连接,但不能在回调中执行任何阻塞操作。如果您需要执行可能会阻塞的某些处理,则必须将其发送到另一个线程池进行处理。此外,如果另一个线程需要与连接进行交互,它只能通过使用提交给连接调度队列的Runnable来完成。
在连接的调度队列上执行Runnable的示例:
connection.getDispatchQueue().execute(new Runnable(){
public void run() {
connection.publish( ..... );
}
});