MQTTdemo里包含了客户端和服务端
下载地址https://download.csdn.net/download/g313105910/18161022
通过订阅主题实现消息传递
通过 builder.WithTcpServer("127.0.0.1", 5550);设置绑定IP和端口
主要代码
using MQTTnet;
using MQTTnet.Client;
using MQTTnet.Protocol;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace MQTTdemo
{
public partial class FrmMain : Form
{
private MqttClient mqttClient = null;
public FrmMain()
{
InitializeComponent();
}
/// <summary>
/// 客户端配置信息
/// </summary>
private IMqttClientOptions Options
{
get
{
MqttClientOptionsBuilder builder = new MqttClientOptionsBuilder();
builder.WithTcpServer(ConfigurationManager.AppSettings["ServerAddress"]);
builder.WithCleanSession(false);
builder.WithCredentials(ConfigurationManager.AppSettings["UserName"], ConfigurationManager.AppSettings["UserPwd"]);
var id = Guid.NewGuid().ToString();
builder.WithClientId(id);
builder.WithTcpServer("127.0.0.1", 5550);
return builder.Build();
}
}
/// <summary>
/// 连接到服务端
/// </summary>
/// <returns></returns>
private void ConnectMqttServer()
{
MqttFactory factory = new MqttFactory();
if (mqttClient == null)
{
mqttClient = (MqttClient)factory.CreateMqttClient();
mqttClient.ApplicationMessageReceived += MqttClient_ApplicationMessageReceived;
mqttClient.Connected += MqttClient_Connected;
mqttClient.Disconnected += (s, e) =>
{
if (!IsClose)
{
Invoke((new Action(() =>
{
if (txtReceiveMessage != null)
{
txtReceiveMessage.AppendText("已断开MQTT连接!" + Environment.NewLine);
}
})));
Invoke((new Action(() =>
{
txtReceiveMessage.AppendText("尝试重连!" + Environment.NewLine);
})));
}
};
}
ConnectToServer();
}
private async void ConnectToServer()
{
try
{
var res = await mqttClient.ConnectAsync(Options);
}
catch (Exception ex)
{
Invoke((new Action(() =>
{
txtReceiveMessage.AppendText($"连接到MQTT服务器失败!" + Environment.NewLine + ex.Message + Environment.NewLine);
})));
}
}
public bool IsClose { get; set; } = false;
private void MqttClient_Connected(object sender, EventArgs e)
{
Invoke((new Action(() =>
{
txtReceiveMessage.AppendText("已连接到MQTT服务器!" + Environment.NewLine);
})));
}
private void MqttClient_ApplicationMessageReceived(object sender, MqttApplicationMessageReceivedEventArgs e)
{
Invoke((new Action(() =>
{
txtReceiveMessage.AppendText($">> {Encoding.UTF8.GetString(e.ApplicationMessage.Payload)}{Environment.NewLine}");
})));
}
private void BtnSubscribe_ClickAsync(object sender, EventArgs e)
{
string topic = txtSubTopic.Text.Trim();
if (string.IsNullOrEmpty(topic))
{
MessageBox.Show("订阅主题不能为空!");
return;
}
if (!mqttClient.IsConnected)
{
MessageBox.Show("MQTT客户端尚未连接!");
return;
}
mqttClient.SubscribeAsync(new List<TopicFilter> {
new TopicFilter(topic, MqttQualityOfServiceLevel.ExactlyOnce)
});
txtReceiveMessage.AppendText($"已订阅[{topic}]主题" + Environment.NewLine);
}
private async void BtnPublish_Click(object sender, EventArgs e)
{
string topic = txtPubTopic.Text.Trim();
if (string.IsNullOrEmpty(topic))
{
MessageBox.Show("发布主题不能为空!");
return;
}
string inputString = txtSendMessage.Text.Trim();
MqttApplicationMessageBuilder builder = new MqttApplicationMessageBuilder();
builder.WithPayload(Encoding.UTF8.GetBytes(inputString));
builder.WithTopic(topic);
builder.WithRetainFlag();
builder.WithExactlyOnceQoS();
await mqttClient.PublishAsync(builder.Build());
}
private void btnDescribe_Click(object sender, EventArgs e)
{
string topic = txtSubTopic.Text.Trim();
if (string.IsNullOrEmpty(topic))
{
MessageBox.Show("退订主题不能为空!");
return;
}
if (!mqttClient.IsConnected)
{
MessageBox.Show("MQTT客户端尚未连接!");
return;
}
mqttClient.UnsubscribeAsync(topic);
txtReceiveMessage.AppendText($"已退订[{topic}]主题" + Environment.NewLine);
}
private void FrmMain_Load(object sender, EventArgs e)
{
Task.Run(async () => { ConnectMqttServer(); });
}
private async void FrmMain_FormClosing(object sender, FormClosingEventArgs e)
{
IsClose = true;
await mqttClient.DisconnectAsync();
mqttClient.Dispose();
}
private void button1_Click(object sender, EventArgs e)
{
ConnectToServer();
}
}
}
MqttClient和MqttServer通过另一种方式实现了参数配置
端口设置
var options = new MqttServerOptions();
options.DefaultEndpointOptions.Port = 5550;
主要代码
using MQTTnet;
using MqttServer.General;
using System;
using System.Collections.ObjectModel;
using System.Text;
using System.Windows;
using MQTTnet.Protocol;
using MQTTnet.Server;
namespace MqttServer
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
ClientInsTances = new ObservableCollection<ClientInstance>();
}
IMqttServer mqttServer; //MQTT服务端实例
string message;
/// <summary>
/// 消息 用于界面显示
/// </summary>
public string Message
{
get { return message; }
set { message = value; }
}
ObservableCollection<ClientInstance> clientInstances; //客户端登录缓存信息
/// <summary>
/// 客户端实例
/// </summary>
public ObservableCollection<ClientInstance> ClientInsTances
{
get { return clientInstances; }
set { clientInstances = value;}
}
//开启MQTT服务
public void OpenMqttServer()
{
mqttServer = new MqttFactory().CreateMqttServer();
var options = new MqttServerOptions();
options.DefaultEndpointOptions.Port = 5550;
//拦截登陆
options.ConnectionValidator = c =>
{
try
{
Message += string.Format("用户尝试登陆:用户ID:{0}\t用户信息:{1}\t用户密码:{2}", c.ClientId, c.Username, c.Password) + "\r\n";
if (string.IsNullOrWhiteSpace(c.Username))
{
Message += string.Format("用户:{0}登陆失败,用户信息为空", c.ClientId) + "\r\n";
c.ReturnCode = MQTTnet.Protocol.MqttConnectReturnCode.ConnectionRefusedBadUsernameOrPassword;
return;
}
//解析用户名和密码,这个地方须要改为查找咱们本身建立的用户名和密码。
if (c.Username == "admin" && c.Password == "123456")
{
c.ReturnCode = MqttConnectReturnCode.ConnectionAccepted;
Message += c.ClientId + " 登陆成功" + "\r\n";
ClientInsTances.Add(new ClientInstance()
{
ClientID = c.ClientId,
UserName = c.Username,
PassWord = c.Password
});
return;
}
else
{
c.ReturnCode = MqttConnectReturnCode.ConnectionRefusedBadUsernameOrPassword;
Message += "用户名密码错误登录失败" + "\r\n";
return;
}
}
catch (Exception ex)
{
Console.WriteLine("登陆失败:" + ex.Message);
c.ReturnCode = MqttConnectReturnCode.ConnectionRefusedIdentifierRejected;
return;
}
};
//拦截订阅
options.SubscriptionInterceptor = context =>
{
try
{
Message += "用户" + context.ClientId + "订阅" + "\r\n";
}
catch (Exception ex)
{
Console.WriteLine("订阅失败:" + ex.Message);
context.AcceptSubscription = false;
}
};
//拦截消息
options.ApplicationMessageInterceptor = context =>
{
try
{
//通常不须要处理消息拦截
// Console.WriteLine(Encoding.UTF8.GetString(context.ApplicationMessage.Payload));
}
catch (Exception ex)
{
Console.WriteLine("消息拦截:" + ex.Message);
}
};
mqttServer.ClientDisconnected += ClientDisconnected;
mqttServer.ClientConnected += MqttServer_ClientConnected;
mqttServer.Started += MqttServer_Started;
//mqttServer.ApplicationMessageReceived += MqttServer_ApplicationMessageReceived;
//mqttServer.ClientConnected += MqttServer_ClientConnected;
//mqttServer.ClientDisconnected += MqttServer_ClientDisconnected;
//mqttServer.StartAsync(Options);
mqttServer.StartAsync(options);
Message += "Mqtt服务启动成功!";
Application.Current.Dispatcher.Invoke(() =>
{
TbInfo.Text = Message;
});
}
private void MqttServer_Started(object sender, EventArgs e)
{
Message += "消息服务启动成功:任意键退出" + "\r\n";
Application.Current.Dispatcher.Invoke(() =>
{
TbInfo.Text = Message;
});
}
private void MqttServer_ClientConnected(object sender, MqttClientConnectedEventArgs e)
{
//客户端连接
Message += e.ClientId + "链接" + "\r\n";
Application.Current.Dispatcher.Invoke(() =>
{
TbInfo.Text = Message;
});
}
private void ClientDisconnected(object sender, MqttClientDisconnectedEventArgs e)
{
//客户端断开
Message += e.ClientId + "断开" + "\r\n";
Application.Current.Dispatcher.Invoke(() =>
{
TbInfo.Text = Message;
});
}
/// <summary>
/// 客户端推送信息 - 用于测试服务推送
/// </summary>
/// <param name="clientID"></param>
/// <param name="message"></param>
public void SendMessage(string clientID, string message)
{
mqttServer.PublishAsync(new MqttApplicationMessage
{
Topic = clientID,
QualityOfServiceLevel = MqttQualityOfServiceLevel.ExactlyOnce,
Retain = false,
Payload = Encoding.UTF8.GetBytes(message),
});
}
private void Strat_Click(object sender, RoutedEventArgs e)
{
OpenMqttServer();
}
private void Test_Click(object sender, RoutedEventArgs e)
{
foreach(var item in clientInstances)
{
try
{
SendMessage(item.ClientID, "测试!");
}
catch(Exception ex)
{
Application.Current.Dispatcher.Invoke(() =>
{
TbInfo.Text = ex.Message + "\r\n";
});
}
}
}
}
}