支持MQTT的broker有很有很多。Moquette是基於Apache Mina 的模型的一個Java MQTT broker。
下面的類是啓動MQTT moquette Broker 的方式
- package com.etrip.mqtt;
- import java.io.File;
- import java.io.IOException;
- import java.net.InetAddress;
- import java.net.InetSocketAddress;
- import org.apache.mina.core.service.IoAcceptor;
- import org.apache.mina.core.service.IoServiceStatistics;
- import org.apache.mina.core.session.IdleStatus;
- import org.apache.mina.core.session.IoSession;
- import org.apache.mina.filter.codec.ProtocolCodecFilter;
- import org.apache.mina.filter.codec.demux.DemuxingProtocolDecoder;
- import org.apache.mina.filter.codec.demux.DemuxingProtocolEncoder;
- import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
- import org.dna.mqtt.moquette.messaging.spi.impl.SimpleMessaging;
- import org.dna.mqtt.moquette.proto.ConnAckEncoder;
- import org.dna.mqtt.moquette.proto.ConnectDecoder;
- import org.dna.mqtt.moquette.proto.DisconnectDecoder;
- import org.dna.mqtt.moquette.proto.DisconnectEncoder;
- import org.dna.mqtt.moquette.proto.MQTTLoggingFilter;
- import org.dna.mqtt.moquette.proto.PingReqDecoder;
- import org.dna.mqtt.moquette.proto.PingRespEncoder;
- import org.dna.mqtt.moquette.proto.PubAckDecoder;
- import org.dna.mqtt.moquette.proto.PubAckEncoder;
- import org.dna.mqtt.moquette.proto.PubCompDecoder;
- import org.dna.mqtt.moquette.proto.PubCompEncoder;
- import org.dna.mqtt.moquette.proto.PubCompMessage;
- import org.dna.mqtt.moquette.proto.PubRecDecoder;
- import org.dna.mqtt.moquette.proto.PubRecEncoder;
- import org.dna.mqtt.moquette.proto.PubRelDecoder;
- import org.dna.mqtt.moquette.proto.PubRelEncoder;
- import org.dna.mqtt.moquette.proto.PublishDecoder;
- import org.dna.mqtt.moquette.proto.PublishEncoder;
- import org.dna.mqtt.moquette.proto.SubAckEncoder;
- import org.dna.mqtt.moquette.proto.SubscribeDecoder;
- import org.dna.mqtt.moquette.proto.UnsubAckEncoder;
- import org.dna.mqtt.moquette.proto.UnsubscribeDecoder;
- import org.dna.mqtt.moquette.proto.messages.ConnAckMessage;
- import org.dna.mqtt.moquette.proto.messages.DisconnectMessage;
- import org.dna.mqtt.moquette.proto.messages.PingRespMessage;
- import org.dna.mqtt.moquette.proto.messages.PubAckMessage;
- import org.dna.mqtt.moquette.proto.messages.PubRecMessage;
- import org.dna.mqtt.moquette.proto.messages.PubRelMessage;
- import org.dna.mqtt.moquette.proto.messages.PublishMessage;
- import org.dna.mqtt.moquette.proto.messages.SubAckMessage;
- import org.dna.mqtt.moquette.proto.messages.UnsubAckMessage;
- import org.dna.mqtt.moquette.server.MQTTHandler;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- /**
- *
- * 在MQTT moquette 中採用MINA作爲底層消息的傳遞方式
- *
- * 本類的目的啓動MQTT moquette Broker 的方式,
- *本文的源代碼來自 moquette-broker-0.1-jar-with-dependencies.jar 中的server類
- * 如果想直接啓動 moquette-broker-0.1-jar-with-dependencies.jar的jar文件方式
- * 可以執行一些命令實現
- * java -jar moquette-broker-0.1-jar-with-dependencies.jar
- *
- *
- * google code 下載MQTT moquette Broker 地址:
- * http://code.google.com/p/moquette-mqtt/
- *
- * GIT 下載MQTT moquette client 地址:
- * https://github.com/fusesource/mqtt-client
- *
- * @author longgangbai
- *
- *
- */
- public class MQTTBrokerProxyServer {
- private static final Logger LOG = LoggerFactory.getLogger(MQTTBrokerProxyServer.class);
- public static final String STORAGE_FILE_PATH = System.getProperty("user.home") + File.separator + "moquette_store.hawtdb";
- private IoAcceptor m_acceptor;
- SimpleMessaging messaging;
- public static void main(String[] args)
- throws IOException
- {
- new MQTTBrokerProxyServer().startServer();
- }
- protected void startServer() throws IOException
- {
- //編碼協議類編碼器
- DemuxingProtocolDecoder decoder = new DemuxingProtocolDecoder();
- decoder.addMessageDecoder(new ConnectDecoder());//連接編碼
- decoder.addMessageDecoder(new PublishDecoder());//發佈編碼
- decoder.addMessageDecoder(new PubAckDecoder());//發佈回執編碼
- decoder.addMessageDecoder(new PubRelDecoder());
- decoder.addMessageDecoder(new PubRecDecoder());//接收編碼
- decoder.addMessageDecoder(new PubCompDecoder());
- decoder.addMessageDecoder(new SubscribeDecoder());//訂閱編碼
- decoder.addMessageDecoder(new UnsubscribeDecoder());//取消訂閱編碼
- decoder.addMessageDecoder(new DisconnectDecoder());//斷開連接編碼
- decoder.addMessageDecoder(new PingReqDecoder());//心跳ping請求編碼
- //解碼協議類解碼器
- DemuxingProtocolEncoder encoder = new DemuxingProtocolEncoder();
- encoder.addMessageEncoder(ConnAckMessage.class, new ConnAckEncoder());//連接解碼
- encoder.addMessageEncoder(SubAckMessage.class, new SubAckEncoder());//訂閱通知解碼
- encoder.addMessageEncoder(UnsubAckMessage.class, new UnsubAckEncoder());//取消訂閱解碼
- encoder.addMessageEncoder(PubAckMessage.class, new PubAckEncoder());//發佈回執解碼
- encoder.addMessageEncoder(PubRecMessage.class, new PubRecEncoder());//接收解碼
- encoder.addMessageEncoder(PubCompMessage.class, new PubCompEncoder());
- encoder.addMessageEncoder(PubRelMessage.class, new PubRelEncoder());
- encoder.addMessageEncoder(PublishMessage.class, new PublishEncoder());//發佈解碼
- encoder.addMessageEncoder(PingRespMessage.class, new PingRespEncoder());//心跳ping相應解碼
- encoder.addMessageEncoder(DisconnectMessage.class,new DisconnectEncoder());//斷開連接解碼
- this.m_acceptor = new NioSocketAcceptor();
- //設置日誌的過濾鏈
- this.m_acceptor.getFilterChain().addLast("logger", new MQTTLoggingFilter("SERVER LOG"));
- //設置編碼的過濾鏈
- this.m_acceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(encoder, decoder));
- //創建業務處理器類
- MQTTHandler handler = new MQTTHandler();
- //創建一個處理消息體的消息
- this.messaging = SimpleMessaging.getInstance();
- this.messaging.init();
- //設置消息體
- handler.setMessaging(this.messaging);
- //設置業務處理器類
- this.m_acceptor.setHandler(handler);
- ((NioSocketAcceptor)this.m_acceptor).setReuseAddress(true);
- ((NioSocketAcceptor)this.m_acceptor).getSessionConfig().setReuseAddress(true);
- this.m_acceptor.getSessionConfig().setReadBufferSize(2048);
- this.m_acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10);
- this.m_acceptor.getStatistics().setThroughputCalculationInterval(10);
- this.m_acceptor.getStatistics().updateThroughput(System.currentTimeMillis());
- //設置端口號
- this.m_acceptor.bind(new InetSocketAddress(1883));
- //獲取綁定的本地的ip地址
- LOG.info("Server binded"+InetAddress.getLocalHost().getHostAddress());
- try {
- Thread.sleep(100000000000000L);
- } catch (InterruptedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- //銷燬broker對象的各種信息
- Runtime.getRuntime().addShutdownHook(new Thread()
- {
- public void run() {
- MQTTBrokerProxyServer.this.stopServer();
- }
- });
- }
- protected void stopServer() {
- LOG.info("Server stopping...");
- this.messaging.stop();
- //Mina IO 統計類
- IoServiceStatistics statistics = this.m_acceptor.getStatistics();
- statistics.updateThroughput(System.currentTimeMillis());
- System.out.println(String.format("Total read bytes: %d, read throughtput: %f (b/s)", new Object[] { Long.valueOf(statistics.getReadBytes()), Double.valueOf(statistics.getReadBytesThroughput()) }));
- System.out.println(String.format("Total read msgs: %d, read msg throughtput: %f (msg/s)", new Object[] { Long.valueOf(statistics.getReadMessages()), Double.valueOf(statistics.getReadMessagesThroughput()) }));
- //關閉相關的會話
- for (IoSession session : this.m_acceptor.getManagedSessions().values()) {
- if ((session.isConnected()) && (!session.isClosing())) {
- session.close(false);
- }
- }
- //銷燬本地IoAcceptor對象
- this.m_acceptor.unbind();
- this.m_acceptor.dispose();
- LOG.info("Server stopped");
- }
- }
-
由 以上代碼可以看出,在發佈訂閱,心跳檢測,連接斷開,連接時候都需要創建相關的協議編碼器對象類中添加相關的編碼器對象。
MQTTHandler類爲主要broker處理髮布和訂閱消息的業務處理器類。