Eclipse paho 實現的基於MqttAsyncClient類的 同步Java 客戶端

package com.wenbo.mqtt;

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JTextArea;
import javax.swing.border.EmptyBorder;

import org.apache.http.util.TextUtils;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttAsyncClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;


public class MqttAsyncClientDemo extends JFrame implements ActionListener {

	/**
	 * 
	 */
	private static final long serialVersionUID = 560476157988482663L;
	private JPanel contentPane;
	private Font useFont = new Font("微軟雅黑", Font.BOLD, 12);
	private JFormattedTextField frmserverIP;
	private JFormattedTextField username;
	private JButton button_connect;
	private JButton button_disconnect;
	private JFormattedTextField toptic_input;
	private JFormattedTextField toptic_titile;
	private JLabel err_infoText;
	private JComboBox<String> comboBox;
	private JButton sendbutton;
	private JTextArea msgtextArea;
	private String brokerIP;
	private String clientId;
	private String msgContent;
	private String sub_topic, pub_topic;
	private int qos = 0;
	private MqttAsyncClient sampleClient;
	private String infoList = "";
	private JButton subbutton;

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					MqttAsyncClientDemo frame = new MqttAsyncClientDemo();
					frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the frame.
	 */
	public MqttAsyncClientDemo() {
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds(100, 100, 484, 419);
		setTitle("MQTT客戶端");
		contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		contentPane.setLayout(null);
		setContentPane(contentPane);

		JLabel lblMqtt = new JLabel("MQTT服務器地址:");
		lblMqtt.setFont(useFont);
		lblMqtt.setBounds(30, 10, 109, 15);
		contentPane.add(lblMqtt);

		frmserverIP = new JFormattedTextField();
		frmserverIP.setText("tcp://219.216.69.138:1883");
		frmserverIP.setBounds(139, 7, 258, 21);
		contentPane.add(frmserverIP);

		JLabel lblNewLabel = new JLabel("用戶名:");
		lblNewLabel.setFont(useFont);
		lblNewLabel.setBounds(40, 41, 54, 15);
		contentPane.add(lblNewLabel);

		username = new JFormattedTextField();
		username.setText("chenbo");
		username.setBounds(139, 38, 99, 21);
		contentPane.add(username);

		button_connect = new JButton("連  接");
		button_connect.setBounds(30, 66, 93, 23);
		button_connect.setFont(useFont);
		button_connect.addActionListener(this);
		button_connect.setActionCommand("connect");
		contentPane.add(button_connect);

		button_disconnect = new JButton("斷  開");
		button_disconnect.setEnabled(false);
		button_disconnect.setFont(useFont);
		button_disconnect.addActionListener(this);
		button_disconnect.setActionCommand("disconnect");
		button_disconnect.setBounds(263, 66, 93, 23);
		contentPane.add(button_disconnect);

		JLabel label = new JLabel("訂閱主題:");
		label.setBounds(40, 111, 83, 15);
		label.setFont(useFont);
		contentPane.add(label);

		toptic_input = new JFormattedTextField();
		toptic_input.setText("info");
		toptic_input.setBounds(139, 108, 99, 21);
		contentPane.add(toptic_input);

		JSeparator separator = new JSeparator();
		separator.setBounds(30, 99, 367, 2);
		contentPane.add(separator);

		subbutton = new JButton("訂  閱");
		subbutton.setFont(useFont);
		subbutton.addActionListener(this);
		subbutton.setActionCommand("sub");
		subbutton.setBounds(263, 107, 93, 23);
		contentPane.add(subbutton);

		JSeparator separator_1 = new JSeparator();
		separator_1.setBounds(30, 139, 367, 2);
		contentPane.add(separator_1);

		JLabel label_1 = new JLabel("發佈消息");
		label_1.setFont(useFont);
		label_1.setBounds(40, 151, 60, 15);
		contentPane.add(label_1);

		JLabel label_2 = new JLabel("主題");
		label_2.setFont(useFont);
		label_2.setBounds(104, 151, 30, 15);
		contentPane.add(label_2);

		toptic_titile = new JFormattedTextField();
		toptic_titile.setText("test");
		toptic_titile.setBounds(139, 148, 99, 21);
		contentPane.add(toptic_titile);

		JLabel label_3 = new JLabel("服務質量");
		label_3.setFont(useFont);
		label_3.setBounds(248, 151, 54, 15);
		contentPane.add(label_3);

		comboBox = new JComboBox<String>();
		comboBox.setBounds(305, 148, 51, 21);
		comboBox.addItem("0");
		comboBox.addItem("1");
		comboBox.addItem("2");
		contentPane.add(comboBox);

		sendbutton = new JButton("發  送");
		sendbutton.setBounds(46, 338, 93, 23);
		sendbutton.addActionListener(this);
		sendbutton.setActionCommand("send");
		contentPane.add(sendbutton);

		JScrollPane scrollPane = new JScrollPane();
		scrollPane.setBounds(40, 179, 316, 149);
		contentPane.add(scrollPane);

		msgtextArea = new JTextArea();
		scrollPane.setViewportView(msgtextArea);

		err_infoText = new JLabel("");
		err_infoText.setForeground(Color.RED);
		err_infoText.setBounds(134, 69, 131, 15);
		err_infoText.setFont(useFont);
		contentPane.add(err_infoText);

		JButton btnClear = new JButton("clear");
		btnClear.setBounds(209, 338, 93, 23);
		btnClear.addActionListener(this);
		btnClear.setActionCommand("clear");
		contentPane.add(btnClear);

	}

	@Override
	public void actionPerformed(ActionEvent e) {
		String command = e.getActionCommand();
		if (command.equals("connect")) {

			MemoryPersistence persistence = new MemoryPersistence();

			try {
				brokerIP = frmserverIP.getText();
				clientId = username.getText();
				if (TextUtils.isEmpty(brokerIP)) {
					err_infoText.setText("輸入服務器地址");
					return;
				}
				if (TextUtils.isEmpty(clientId)) {
					err_infoText.setText("輸入ID");
					return;
				}
				sampleClient = new MqttAsyncClient(brokerIP, clientId, persistence);
				MqttConnectOptions connOpts = new MqttConnectOptions();
				connOpts.setCleanSession(true);
				System.out.println("Connecting to broker: " + brokerIP);
				sampleClient.connect(connOpts);

				System.out.println("Connected");
				err_infoText.setText("已連接");
				button_disconnect.setEnabled(true);
				button_connect.setEnabled(false);

				sampleClient.setCallback(new MqttCallback() {

					@Override
					public void messageArrived(String topic, MqttMessage message) throws Exception {
						String msg = new String(message.getPayload());

						System.out.println("接收消息主題 : " + topic);
						System.out.println("接收消息Qos : " + message.getQos());
						System.out.println("接收消息內容 : " + message.toString());
						System.out.println("接收消息id : " + message.getId());

						String info = message.toString();
						infoList += info + "\n";
						msgtextArea.setText(infoList);
						Thread.sleep(10000);
					}

					@Override
					public void deliveryComplete(IMqttDeliveryToken arg0) {
						try {
							System.out.println(arg0.getMessage());
						} catch (MqttException e1) {
							e1.printStackTrace();
						}

					}

					@Override
					public void connectionLost(Throwable err) {
						err_infoText.setText("連接丟失");
						System.out.println("連接丟失");
						System.out.println(err.getMessage());

					}
				});

			} catch (MqttException me) {
				System.out.println("reason " + me.getReasonCode());
				System.out.println("msg " + me.getMessage());
				System.out.println("loc " + me.getLocalizedMessage());
				System.out.println("cause " + me.getCause());
				System.out.println("excep " + me);
				err_infoText.setText("hi:" + me.getMessage());
				button_disconnect.setEnabled(false);
				button_connect.setEnabled(true);
				me.printStackTrace();
			}

		} else if (command.equals("sub")) {
			sub_topic = toptic_input.getText();
			if (TextUtils.isEmpty(sub_topic)) {
				err_infoText.setText("輸入訂閱主題");
				return;
			}
			try {
				sampleClient.subscribe(sub_topic, 0);
				subbutton.setEnabled(false);
			} catch (MqttException e1) {
				e1.printStackTrace();
			}

		} else if (command.equals("send")) {
			pub_topic = toptic_titile.getText();
			msgContent = msgtextArea.getText();
			if (TextUtils.isEmpty(pub_topic)) {
				err_infoText.setText("輸入發送主題");
				return;
			}
			if (TextUtils.isEmpty(msgContent)) {
				err_infoText.setText("輸入消息內容");
				return;
			}
			MqttMessage message = new MqttMessage(msgContent.getBytes());
			String qoset = comboBox.getSelectedItem().toString();
			if (qoset == "0") {
				qos = 0;
			} else if (qoset == "1") {
				qos = 1;
			} else {
				qos = 2;
			}
			message.setQos(qos);
			try {
				sampleClient.publish(pub_topic, message);
			} catch (MqttException e1) {
				e1.printStackTrace();
				err_infoText.setText(e1.getMessage());
			}

		} else if (command.equals("clear")) {
			msgtextArea.setText("");
			infoList = "";

		} else if (command.equals("disconnect")) {
			if (sampleClient != null) {
				try {
					sampleClient.disconnect();
					button_connect.setEnabled(true);
					button_disconnect.setEnabled(false);
					err_infoText.setText("已斷開");
				} catch (MqttException e1) {
					e1.printStackTrace();
				}
			}
		}
	}
}

編寫以上代碼主要目的是想通過親身實現(官網有相關說明)弄清楚MQTT 的同步和異步究竟有什麼區別。經過分別使用MqttAsyncClient 和MqttClient 進行嘗試。我在messageArrived 中收到消息後sleep 一段時間模擬處理數據。如果用同步模式,則點擊發送消息發送不出去。如果是異步模式,則可以正常發送消息。異步模式下發送和接收是兩條線程分別實現的。但接收部分不是多線程,即如果messageArrived 方法接收到消息後不開啓新的線程而長時間處理數據的話,則只能等待處理完之後才能再接收後續的消息。

參考:
Eclipse paho實現的MQTT Java客戶端_文博那些事兒-CSDN博客
https://blog.csdn.net/chenbo163/article/details/78742218

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章