C#MQTT编程07--MQTT服务器和客户端(wpf版)

这篇具有很好参考价值的文章主要介绍了C#MQTT编程07--MQTT服务器和客户端(wpf版)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1、前言

上篇完成了winform版的mqtt服务器和客户端,实现了订阅和发布,效果666,长这样

C#MQTT编程07--MQTT服务器和客户端(wpf版),C#Mqtt网络编程,c#,wpf,开发语言,mqttnet服务器,mqttnet客户端,mqttnet搭建过程,mqtt通信

 这节要做的wpf版,长这样,效果也是帅BBBB帅,wpf技术是cs程序软件的福音。

C#MQTT编程07--MQTT服务器和客户端(wpf版),C#Mqtt网络编程,c#,wpf,开发语言,mqttnet服务器,mqttnet客户端,mqttnet搭建过程,mqtt通信

 wpf的基础知识和案例项目可以看我的另一个专栏系列文章,这里直接干搞,开发环境依然是vs2022,.netframework 4.8,mqttnet3.x。

WPF真入门教程

2、服务器搭建

1、创建项目方案

C#MQTT编程07--MQTT服务器和客户端(wpf版),C#Mqtt网络编程,c#,wpf,开发语言,mqttnet服务器,mqttnet客户端,mqttnet搭建过程,mqtt通信

C#MQTT编程07--MQTT服务器和客户端(wpf版),C#Mqtt网络编程,c#,wpf,开发语言,mqttnet服务器,mqttnet客户端,mqttnet搭建过程,mqtt通信

 2、添加包组件MQTTNET 

C#MQTT编程07--MQTT服务器和客户端(wpf版),C#Mqtt网络编程,c#,wpf,开发语言,mqttnet服务器,mqttnet客户端,mqttnet搭建过程,mqtt通信

3、创建相关的目录及文件 

 C#MQTT编程07--MQTT服务器和客户端(wpf版),C#Mqtt网络编程,c#,wpf,开发语言,mqttnet服务器,mqttnet客户端,mqttnet搭建过程,mqtt通信

样式文件CommonStyle.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Style x:Key="ButtonStyle" TargetType="Button">
        <Setter Property="Background" Value="#3F85FF"></Setter>
        <Setter Property="Foreground" Value="White"></Setter>
        <Setter Property="FocusVisualStyle" Value="{x:Null}"></Setter>
        <Setter Property="Margin" Value="5"></Setter>
        <Setter Property="FontSize" Value="16"></Setter>
        <!--模板的样式-->
        <Setter Property="Template">
            <Setter.Value>
                <!--Button单选按钮样式-->
                <ControlTemplate TargetType="Button">
                    <Grid >
                        <Border Background="{TemplateBinding Background}" CornerRadius="5" >
                            <TextBlock Margin="10 5 10 5" Text="{TemplateBinding Content}" FontSize="{TemplateBinding FontSize}" HorizontalAlignment="Center" VerticalAlignment="Center"></TextBlock>
                        </Border>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <!--鼠标放上去时的触发器-->
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter Property="Background" Value="DarkOliveGreen" ></Setter>
                        </Trigger>
                    </ControlTemplate.Triggers> 
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

4、设置UI布局界面 

 C#MQTT编程07--MQTT服务器和客户端(wpf版),C#Mqtt网络编程,c#,wpf,开发语言,mqttnet服务器,mqttnet客户端,mqttnet搭建过程,mqtt通信

<Window x:Class="MQTTNETServerWPF.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:MQTTNETServerWPF.ViewModel"
        mc:Ignorable="d" Background="Transparent" WindowStartupLocation="CenterScreen"
        FontSize="13" FontFamily="Microsoft YaHei" FontWeight="ExtraLight" Foreground="#333"
        Title="MainWindow" Height="550" Width="890">
    <WindowChrome.WindowChrome>
        <WindowChrome GlassFrameThickness="-1"/>
    </WindowChrome.WindowChrome>
    <Window.DataContext>
        <local:MainWindowViewModel/>
    </Window.DataContext>
    <Grid ShowGridLines="true"  >
        <Grid.RowDefinitions>
            <RowDefinition Height="70"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <TextBlock Grid.Row="0" FontWeight="Bold" Background="BlanchedAlmond"  Text="WPF版MQTT服务器程序" FontSize="25" VerticalAlignment="Center" Margin="6,20,0,0" Foreground="#666"   />
        <Grid Grid.Row="1">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="220"/>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>
            <Border BorderBrush="#EEE" BorderThickness="0,0,1,0"/>

            <!--左侧布局-->
            <StackPanel Grid.Column="0" Margin="20" >
                <TextBlock Text="主机地址"/>
                <TextBox Text="{Binding Server.ServerIP}" Height="30" VerticalContentAlignment="Center" Padding="5,0" Margin="0,10"  />
                <TextBlock Text="端口号" Margin="0,10,0,0"/>
                <TextBox Text="{Binding Server.ServerPort}" Height="30" VerticalContentAlignment="Center" Padding="5,0" Margin="0,10"  />
                <TextBlock Text="连接账号" Margin="0,10,0,0"/>
                <TextBox Text="{Binding Server.ServerName}"  Height="30" VerticalContentAlignment="Center" Padding="5,0" Margin="0,10"    />
                <TextBlock Text="连接密码" Margin="0,10,0,0"/>
                <TextBox Text="{Binding Server.ServerPwd}" Height="30" VerticalContentAlignment="Center" Padding="5,0" Margin="0,10"  />
                <Button Content="启动服务" Margin="0,30,0,0" Height="30"  Command="{Binding StartCommand}" Style="{StaticResource ButtonStyle}" />
                <Button Content="停止服务" Margin="0,10" Height="30"  Command="{Binding StopCommand}"  Style="{StaticResource ButtonStyle}"/>
            </StackPanel>

            <!--右侧布局-->
            <Grid Grid.Column="1">
                <Grid.RowDefinitions>
                    <RowDefinition Height="2*"/>
                    <RowDefinition Height="3*"/>
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition/>
                    <ColumnDefinition/>
                </Grid.ColumnDefinitions>
                <GridSplitter VerticalAlignment="Bottom" HorizontalAlignment="Stretch" Height="4" Background="#F7F9FA" Grid.ColumnSpan="2" Margin="0,0,3,0"/>

                <Grid Margin="20,20,10,15">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="30"/>
                        <RowDefinition/>
                    </Grid.RowDefinitions>
                    <TextBlock Text="在线Client列表"/>
                    <ListBox Grid.Row="1"   ItemsSource="{Binding ClientsList}"/>
                </Grid>

                <Grid Margin="10,20,20,15" Grid.Column="1">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="30"/>
                        <RowDefinition/>
                    </Grid.RowDefinitions>
                    <TextBlock Text="Topic主题列表"/>
                    <ListView Grid.Row="1"   ItemsSource="{Binding TopicsList}">
                    </ListView>
                </Grid>

                <Grid Grid.Row="1" Grid.ColumnSpan="2" Margin="20,10,20,20">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="30"/>
                        <RowDefinition/>
                    </Grid.RowDefinitions>
                    <TextBlock Text="消息"/>
                    <TextBox  Grid.Row="1"   x:Name="txtRich" ToolTip="右键清理内容" Text="{Binding ConnectWords}" Height="200" Background="White" VerticalContentAlignment="Top" Padding="3,0" Margin="10,9,10,10"    >
                        <!--添加一个右键菜单的功能,即清空-->
                        <TextBox.ContextMenu>
                            <ContextMenu>
                                <MenuItem x:Name="menuClear" Click="miClear_Click"  Header="清空内容"></MenuItem>
                            </ContextMenu>
                        </TextBox.ContextMenu>
                    </TextBox>
                </Grid>
            </Grid>
        </Grid>
    </Grid>
</Window>

5、视图模型,属性绑定和命令绑定

C#MQTT编程07--MQTT服务器和客户端(wpf版),C#Mqtt网络编程,c#,wpf,开发语言,mqttnet服务器,mqttnet客户端,mqttnet搭建过程,mqtt通信

完整代码:

using MQTTnet.Client.Receiving;
using MQTTnet;
using MQTTnet.Server;
using MQTTNETServerWPF.Command;
using MQTTNETServerWPF.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using System.Collections.ObjectModel;
using MQTTnet.Certificates;
using MQTTnet.Protocol;
using System.Runtime.Remoting.Messaging;

namespace MQTTNETServerWPF.ViewModel
{
    public class MainWindowViewModel : ViewModelBase
    {
       
        private IMqttServer mqttserver;//mqtt服务器
        List<TopicItem> Topics = new List<TopicItem>();

        public MainWindowViewModel()
        {
            //创建服务器对象
            mqttserver = new MqttFactory().CreateMqttServer();
            mqttserver.ApplicationMessageReceivedHandler =
                new MqttApplicationMessageReceivedHandlerDelegate(new Action<MqttApplicationMessageReceivedEventArgs>(Server_ApplicationMessageReceived));//绑定消息接收事件
            mqttserver.ClientConnectedHandler =
                new MqttServerClientConnectedHandlerDelegate(new Action<MqttServerClientConnectedEventArgs>(Server_ClientConnected));//绑定客户端连接事件
            mqttserver.ClientDisconnectedHandler = new MqttServerClientDisconnectedHandlerDelegate(new Action<MqttServerClientDisconnectedEventArgs>(Server_ClientDisconnected));//绑定客户端断开事件
            mqttserver.ClientSubscribedTopicHandler = new MqttServerClientSubscribedHandlerDelegate(new Action<MqttServerClientSubscribedTopicEventArgs>(Server_ClientSubscribedTopic));//绑定客户端订阅主题事件
            mqttserver.ClientUnsubscribedTopicHandler = new MqttServerClientUnsubscribedTopicHandlerDelegate(new Action<MqttServerClientUnsubscribedTopicEventArgs>(Server_ClientUnsubscribedTopic));//绑定客户端退订主题事件
            mqttserver.StartedHandler = new MqttServerStartedHandlerDelegate(new Action<EventArgs>(Server_Started));//绑定服务端启动事件
            mqttserver.StoppedHandler = new MqttServerStoppedHandlerDelegate(new Action<EventArgs>(Server_Stopped));//绑定服务端停止事件
        }

        #region 方法

        /// 绑定消息接收事件
        /// </summary>
        /// <param name="e"></param>
        private void Server_ApplicationMessageReceived(MqttApplicationMessageReceivedEventArgs e)
        {
            string msg = e.ApplicationMessage.ConvertPayloadToString();
            WriteLog(">>> 收到消息:" + msg + ",QoS =" + e.ApplicationMessage.QualityOfServiceLevel + ",客户端=" + e.ClientId + ",主题:" + e.ApplicationMessage.Topic);
        }

        /// <summary>
        /// 绑定客户端连接事件
        /// </summary>
        /// <param name="e"></param>
        private void Server_ClientConnected(MqttServerClientConnectedEventArgs e)
        {
            Task.Run(() =>
            {
                App.Current.Dispatcher.Invoke(() =>
                {
                    this.ClientsList.Add(e.ClientId);
                });
                WriteLog(">>> 客户端" + e.ClientId + "连接");
            });
        }

        /// <summary>
        /// 绑定客户端断开事件
        /// </summary>
        /// <param name="e"></param>
        private void Server_ClientDisconnected(MqttServerClientDisconnectedEventArgs e)
        {
            Task.Run(() =>
            {
                App.Current.Dispatcher.Invoke(() =>
                {
                    this.ClientsList.Remove(e.ClientId);
                });
                WriteLog(">>> 客户端" + e.ClientId + "断开");
            });
        }

        /// <summary>
        /// 绑定客户端订阅主题事件
        /// </summary>
        /// <param name="e"></param>
        private void Server_ClientSubscribedTopic(MqttServerClientSubscribedTopicEventArgs e)
        {
            Task.Run(() =>
            {
                App.Current.Dispatcher.Invoke(() =>
                {
                    var topic = Topics.FirstOrDefault(t => t.Topic == e.TopicFilter.Topic);
                    if (topic == null)
                    {
                        topic = new TopicItem { Topic = e.TopicFilter.Topic, Count = 0 };
                        Topics.Add(topic);
                    }
                    if (!topic.Clients.Exists(c => c == e.ClientId))
                    {
                        topic.Clients.Add(e.ClientId);
                        topic.Count++;
                    }

                    this.TopicsList.Clear();
                    foreach (var item in this.Topics)
                    {
                        this.TopicsList.Add($"{item.Topic}:{item.Count}");
                    }
                });
                WriteLog(">>> 客户端" + e.ClientId + "订阅主题" + e.TopicFilter.Topic);
            });
        }

        /// <summary>
        /// 绑定客户端退订主题事件
        /// </summary>
        /// <param name="e"></param>
        private void Server_ClientUnsubscribedTopic(MqttServerClientUnsubscribedTopicEventArgs e)
        {
            Task.Run(() =>
            {
                App.Current.Dispatcher.Invoke(() =>
                {
                    var topic = Topics.FirstOrDefault(t => t.Topic == e.TopicFilter);
                    if (topic != null)
                    {
                        topic.Count--;
                        topic.Clients.Remove(e.ClientId);
                    }

                    this.TopicsList.Clear();
                    foreach (var item in this.Topics)
                    {
                        this.TopicsList.Add($"{item.Topic}:{item.Count}");
                    }
                });
                WriteLog(">>> 客户端" + e.ClientId + "退订主题" + e.TopicFilter);
            });
        }

        /// <summary>
        /// 绑定服务端启动事件
        /// </summary>
        /// <param name="e"></param>
        private void Server_Started(EventArgs e)
        {
            WriteLog(">>> 服务端已启动!");
        }

        /// <summary>
        /// 绑定服务端停止事件
        /// </summary>
        /// <param name="e"></param>
        private void Server_Stopped(EventArgs e)
        {
            WriteLog(">>> 服务端已停止!");
        }

        /// <summary>
        /// 显示日志
        /// </summary>
        /// <param name="message"></param>
        public void WriteLog(string message)
        {
            Task.Run(() =>
            {
                App.Current.Dispatcher.Invoke(() =>
                {
                    ConnectWords = message + "\r";
                });
            });
        }

        #endregion



        #region 属性
        private MqttServerModel server = new MqttServerModel("127.0.0.1", "1869", "boss", "1234");//服务器实体
        /// <summary>
        /// 当前服务器对象
        /// </summary>
        public MqttServerModel Server
        {
            get { return server; }
            set
            {
                server = value;
                OnPropertyChanged();
            }
        }

        private string connectWords = "";
        /// <summary>
        /// 连接状态
        /// </summary>
        public string ConnectWords
        {
            get { return connectWords; }
            set
            {
                connectWords = value;
                OnPropertyChanged();
            }
        }

        private ObservableCollection<string> clientsList = new ObservableCollection<string>();
        /// <summary>
        /// 客户列表
        /// </summary>
        public ObservableCollection<string> ClientsList
        {
            get { return clientsList; }
            set
            {
                clientsList = value;
                OnPropertyChanged();
            }
        }

        private ObservableCollection<string> topicsList = new ObservableCollection<string>();
        /// <summary>
        /// 主题列表
        /// </summary>
        public ObservableCollection<string> TopicsList
        {
            get { return topicsList; }
            set
            {
                topicsList = value;
                OnPropertyChanged();
            }
        }
        #endregion




        #region 命令
        /// <summary>
        /// 启动命令
        /// </summary>
        [Obsolete]
        public ICommand StartCommand
        {
            get
            {
                return new RelayCommand(async o =>
                {
                    var optionBuilder = new MqttServerOptionsBuilder()
                .WithDefaultEndpointBoundIPAddress(System.Net.IPAddress.Parse(Server.ServerIP))
                .WithDefaultEndpointPort(int.Parse(Server.ServerPort))
                .WithDefaultCommunicationTimeout(TimeSpan.FromMilliseconds(5000))
                .WithConnectionValidator(t =>
                {
                    string un = "", pwd = "";
                    un = Server.ServerName;
                    pwd = Server.ServerPwd;
                    if (t.Username != un || t.Password != pwd)
                    {
                        t.ReturnCode = MqttConnectReturnCode.ConnectionRefusedBadUsernameOrPassword;
                    }
                    else
                    {
                        t.ReturnCode = MqttConnectReturnCode.ConnectionAccepted;
                    }
                });
                    var option = optionBuilder.Build();
                    //启动
                    await mqttserver.StartAsync(option);
                }
                );
            }
        }

        /// <summary>
        /// 启动命令
        /// </summary>
        [Obsolete]
        public ICommand StopCommand
        {
            get
            {
                return new RelayCommand(async o =>
                { 
                    if (server != null)
                    {
                        await mqttserver.StopAsync();
                    } 
                });
            }
        }
        #endregion

    }
}

 注意一个地方,就是给文本框添加了一个右键“清空”的功能,看看是怎么样实现的?

C#MQTT编程07--MQTT服务器和客户端(wpf版),C#Mqtt网络编程,c#,wpf,开发语言,mqttnet服务器,mqttnet客户端,mqttnet搭建过程,mqtt通信

 6、启动测试服务器

启动成功,服务器kokokokoko!!!!

C#MQTT编程07--MQTT服务器和客户端(wpf版),C#Mqtt网络编程,c#,wpf,开发语言,mqttnet服务器,mqttnet客户端,mqttnet搭建过程,mqtt通信

C#MQTT编程07--MQTT服务器和客户端(wpf版),C#Mqtt网络编程,c#,wpf,开发语言,mqttnet服务器,mqttnet客户端,mqttnet搭建过程,mqtt通信

 3、客户端创建

1、添加项目MQTTNETClientWPF

C#MQTT编程07--MQTT服务器和客户端(wpf版),C#Mqtt网络编程,c#,wpf,开发语言,mqttnet服务器,mqttnet客户端,mqttnet搭建过程,mqtt通信

2、添加客户端的组件

 C#MQTT编程07--MQTT服务器和客户端(wpf版),C#Mqtt网络编程,c#,wpf,开发语言,mqttnet服务器,mqttnet客户端,mqttnet搭建过程,mqtt通信

3、创建相关的类文件及目录 

 C#MQTT编程07--MQTT服务器和客户端(wpf版),C#Mqtt网络编程,c#,wpf,开发语言,mqttnet服务器,mqttnet客户端,mqttnet搭建过程,mqtt通信

4、设计UI布局

 布局仔细 看下C#MQTT编程07--MQTT服务器和客户端(wpf版),C#Mqtt网络编程,c#,wpf,开发语言,mqttnet服务器,mqttnet客户端,mqttnet搭建过程,mqtt通信

<Window x:Class="MQTTNETClientWPF.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:MQTTNETClientWPF.ViewModel"
              mc:Ignorable="d" Background="Transparent" WindowStartupLocation="CenterScreen"
        FontSize="13" FontFamily="Microsoft YaHei" FontWeight="ExtraLight" Foreground="#333"
        Title="MainWindow" Height="600" Width="850">
    <WindowChrome.WindowChrome>
        <WindowChrome GlassFrameThickness="-1"/>
    </WindowChrome.WindowChrome>
    <Window.DataContext>
        <local:MainWindowViewModel/>
    </Window.DataContext>
    <Grid  ShowGridLines="true" >
        <Grid.RowDefinitions>
            <RowDefinition Height="70"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <TextBlock Grid.Row="0" FontWeight="Bold"  Text="WPF版MQTT客户端程序" FontSize="25" VerticalAlignment="Center" Margin="6,20,0,0" Foreground="#666" Background="BlanchedAlmond"  />

        <Grid Grid.Row="1">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="220"/>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>
            <Border BorderBrush="#EEE" BorderThickness="0,0,1,0"/>

            <StackPanel Margin="20">
                <TextBlock Text="主机地址"/>
                <TextBox Text="{Binding Client.ServerIP}" Height="30" VerticalContentAlignment="Center" Padding="5,0" Margin="0,10" Name="tbHostAddr"/>
                <TextBlock Text="端口号" Margin="0,5,0,0"/>
                <TextBox  Text="{Binding Client.ServerPort}" Height="30" VerticalContentAlignment="Center" Padding="5,0" Margin="0,10"   Name="tbHostPort"/>
                <TextBlock Text="连接账号" Margin="0,5,0,0"/>
                <TextBox  Text="{Binding Client.ServerName}" Height="30" VerticalContentAlignment="Center" Padding="5,0" Margin="0,10" Name="tbUsername"/>
                <TextBlock Text="连接密码" Margin="0,5,0,0"/>
                <TextBox Text="{Binding Client.ServerPwd}" Height="30" VerticalContentAlignment="Center" Padding="5,0" Margin="0,10"  Name="tbPassword"/>
                <TextBlock Text="客户端ID" Margin="0,5,0,0"/>
                <TextBox Text="{Binding Client.ClientId}" Height="30" VerticalContentAlignment="Center" Padding="5,0" Margin="0,10"   Name="tbClientId"/>
                <Button Content="连接" Margin="0,30,0,0" Height="30" Command="{Binding OpenCommand}"  Style="{StaticResource ButtonStyle}"/>
                <Button Content="断开" Margin="0,10" Height="30"  Command="{Binding CloseCommand}" Style="{StaticResource ButtonStyle}"/>
            </StackPanel>

            <Grid Grid.Column="1" Margin="20,10">
                <Grid.RowDefinitions>
                    <RowDefinition Height="auto"/>
                    <RowDefinition Height="auto"/>
                    <RowDefinition/>
                </Grid.RowDefinitions>

                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="30"/>
                        <RowDefinition Height="50"/>
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="auto"/>
                        <ColumnDefinition/>
                        <ColumnDefinition Width="auto"/>
                    </Grid.ColumnDefinitions>
                    <Border Background="#F7F9FA" Grid.ColumnSpan="3"/>
                    <TextBlock Text="订阅" VerticalAlignment="Center" Margin="5,0"/>
                    <TextBlock Text="主题" Grid.Row="1" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="5,0"/>
                    <TextBox Text="{Binding Topic}" Grid.Row="1" Height="30" Padding="5,0" VerticalContentAlignment="Center" Grid.Column="1"  Name="tbTopic"/>
                    <Button Width="50" Grid.Row="1" Height="30" Content="订阅" Grid.Column="2" Margin="5,10,0,10"   Command="{Binding SubscriteCommand}"  Style="{StaticResource ButtonStyle}"  HorizontalAlignment="Left"/>
                </Grid>

                <Grid Grid.Row="1" Margin="0,20">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="30"/>
                        <RowDefinition Height="50"/>
                        <RowDefinition Height="30"/>
                        <RowDefinition/>
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="auto"/>
                        <ColumnDefinition/>
                        <ColumnDefinition Width="auto"/>
                    </Grid.ColumnDefinitions>
                    <Border Background="#F7F9FA" Grid.ColumnSpan="3"/>
                    <TextBlock Text="发布" VerticalAlignment="Center" Margin="5,0"/>
                    <TextBlock Text="主题" Grid.Row="1" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="5,0"/>
                    <TextBox Text="{Binding Topic}" Grid.Row="1" Height="30" Padding="5,0" VerticalContentAlignment="Center" Grid.Column="1"   Name="tbPubTopic"/>
                    <TextBlock Text="内容" Grid.Row="2" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="5,0"/>
                    <TextBox Text="{Binding Pubmsg}"  Grid.Row="2" Height="30" Padding="5,0" VerticalContentAlignment="Center" Grid.Column="1"  Name="tbContent"/>
                    <Button Width="50" Grid.Row="2" Height="30"  Content="发布" Grid.Column="2" Margin="5,0,5,0"  Command="{Binding PublishCommand}"  Style="{StaticResource ButtonStyle}"  VerticalAlignment="Top"/>
                </Grid>

                <Grid Grid.Row="2" Margin="0,10,0,0">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="30"/>
                        <RowDefinition/>
                    </Grid.RowDefinitions>
                    <Border Background="#F7F9FA" Grid.ColumnSpan="3"/>
                    <TextBlock Text="消息" VerticalAlignment="Center" Margin="5,0"/>
                    <TextBox  Grid.Row="1"  x:Name="txtRich" ToolTip="右键清理内容" Text="{Binding ConnectWords}" Height="200"  Background="White" VerticalContentAlignment="Top"  Padding="3,0" Margin="10,9,75,10"  >
                        <!--添加一个右键菜单的功能,即清空-->
                        <TextBox.ContextMenu>
                            <ContextMenu>
                                <MenuItem x:Name="menuClear" Click="miClear_Click"  Header="清空内容"></MenuItem>
                            </ContextMenu>
                        </TextBox.ContextMenu>
                    </TextBox>
                </Grid>
            </Grid>
        </Grid>
    </Grid>
</Window>

5、视图模型viewmodel

模型类的属性绑定和命令绑定,数据驱动控件,即Mvvm渲染方法

using MQTTnet.Client.Options;
using MQTTnet.Client;
using MQTTnet.Extensions.ManagedClient;
using MQTTNETClientWPF.Command;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using MQTTNETClientWPF.Model;
using MQTTnet;

namespace MQTTNETClientWPF.ViewModel
{
    public class MainWindowViewModel : ViewModelBase
    {
        private IManagedMqttClient mqttClient; //mqtt客户端


        public MainWindowViewModel()
        {
            var factory = new MqttFactory();
            mqttClient = factory.CreateManagedMqttClient();//创建客户端对象

            //绑定断开事件
            mqttClient.UseDisconnectedHandler(async ee =>
            {
                WriteLog(DateTime.Now.ToString() + "与服务器之间的连接断开了,正在尝试重新连接");
                // 等待 5s 时间
                await Task.Delay(TimeSpan.FromSeconds(5));
                try
                {
                    mqttClient.UseConnectedHandler(cc =>
                    {
                        WriteLog(">>> 连接到服务成功!");
                    });
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"重新连接服务器失败:{ex}");
                }
            });

            //绑定接收事件
            mqttClient.UseApplicationMessageReceivedHandler(aa =>
            {
                 try
                {
                    string msg = aa.ApplicationMessage.ConvertPayloadToString();
                    WriteLog(">>> 消息:" + msg + ",QoS =" + aa.ApplicationMessage.QualityOfServiceLevel + ",客户端=" + aa.ClientId + ",主题:" + aa.ApplicationMessage.Topic);
                }
                catch (Exception ex)
                {
                    WriteLog($"+ 消息 = " + ex.Message);
                } 
            });

            //绑定连接事件
            mqttClient.UseConnectedHandler(ee =>
            {
                WriteLog(">>> 连接到服务");
            });
        }

        /// <summary>
        /// 显示日志
        /// </summary>
        /// <param name="message"></param> 
        public void WriteLog(string message)
        {
            Task.Run(() =>
            {
                App.Current.Dispatcher.Invoke(() =>
                {
                    ConnectWords = message + "\r";
                });
            });
        }

        #region 属性

        private MqttClientModel client = new MqttClientModel("127.0.0.1", "1869", "boss", "1234", "c1");//服务器实体

        /// <summary>
        /// 连接对象
        /// </summary>
        public MqttClientModel Client
        {
            get { return client; }
            set
            {
                client = value;
                OnPropertyChanged();
            }
        }

        private string connectWords = "";
        /// <summary>
        /// 连接状态
        /// </summary>
        public string ConnectWords
        {
            get { return connectWords; }
            set
            {
                connectWords = value;
                OnPropertyChanged();
            }
        }

        private string topic = "shanghai";
        /// <summary>
        /// 主题
        /// </summary>
        public string Topic
        {
            get { return topic; }
            set
            {
                topic = value;
                OnPropertyChanged();
            }
        }

        private string pubmsg = "0103";
        /// <summary>
        /// 发布
        /// </summary>
        public string Pubmsg
        {
            get { return pubmsg; }
            set
            {
                pubmsg = value;
                OnPropertyChanged();
            }
        }
        #endregion


        #region 命令
        /// <summary>
        /// 连接命令
        /// </summary> 
        public ICommand OpenCommand
        {
            get
            {
                return new RelayCommand(async o =>
                {
                    var mqttClientOptions = new MqttClientOptionsBuilder()
                             .WithClientId(this.Client.ClientId)
                             .WithTcpServer(this.Client.ServerIP, int.Parse(this.Client.ServerPort))
                             .WithCredentials(this.Client.ServerName, this.Client.ServerPwd);

                    var options = new ManagedMqttClientOptionsBuilder()
                                .WithAutoReconnectDelay(TimeSpan.FromSeconds(5))
                                .WithClientOptions(mqttClientOptions.Build())
                                .Build();
                    //开启
                    var t = mqttClientOptions;
                    await mqttClient.StartAsync(options);
                });
            }
        }

        /// <summary>
        /// 断开命令
        /// </summary> 
        public ICommand CloseCommand
        {
            get
            {
                return new RelayCommand(async o =>
                {
                    if (mqttClient != null)
                    {
                        if (mqttClient.IsStarted)
                        {
                            await mqttClient.StopAsync();
                        }
                        mqttClient.Dispose();
                    }
                });
            }
        }

        /// <summary>
        /// 订阅命令
        /// </summary> 
        [Obsolete]
        public ICommand SubscriteCommand
        {
            get
            {
                return new RelayCommand(async o =>
                {
                    if (string.IsNullOrWhiteSpace(this.Topic))
                    {
                        WriteLog(">>> 请输入主题");
                        return;
                    }

                    //在 MQTT 中有三种 QoS 级别: 
                    //At most once(0) 最多一次
                    //At least once(1) 至少一次
                    //Exactly once(2) 恰好一次
                    //await mqttClient.SubscribeAsync(new TopicFilterBuilder().WithTopic(this.tbTopic.Text).WithAtMostOnceQoS().Build());//最多一次, QoS 级别0
                    await mqttClient.SubscribeAsync(new TopicFilterBuilder().WithTopic(this.Topic).WithAtLeastOnceQoS().Build());//恰好一次, QoS 级别1 

                    WriteLog($">>> 成功订阅 {this.Topic}");
                });
            }
        }

        /// <summary>
        /// 发布命令
        /// </summary> 
        public ICommand PublishCommand
        {
            get
            {
                return new RelayCommand(async o =>
                {
                    if (string.IsNullOrWhiteSpace(this.Topic))
                    {
                        WriteLog(">>> 请输入主题");
                        return;
                    }
                    var result = await mqttClient.PublishAsync(
                        this.Topic,
                        this.Pubmsg,
                        MQTTnet.Protocol.MqttQualityOfServiceLevel.AtLeastOnce);//恰好一次, QoS 级别1 
                    WriteLog($">>> 主题:{this.Topic},消息:{this.Pubmsg},结果: {result.ReasonCode}");
                });
            }
        }

        #endregion

    }
}

6、启动客户端

比较屌

C#MQTT编程07--MQTT服务器和客户端(wpf版),C#Mqtt网络编程,c#,wpf,开发语言,mqttnet服务器,mqttnet客户端,mqttnet搭建过程,mqtt通信

C#MQTT编程07--MQTT服务器和客户端(wpf版),C#Mqtt网络编程,c#,wpf,开发语言,mqttnet服务器,mqttnet客户端,mqttnet搭建过程,mqtt通信

4、测试mqtt

 C#MQTT编程07--MQTT服务器和客户端(wpf版),C#Mqtt网络编程,c#,wpf,开发语言,mqttnet服务器,mqttnet客户端,mqttnet搭建过程,mqtt通信

1、启动服务器,客户端连接成功

C#MQTT编程07--MQTT服务器和客户端(wpf版),C#Mqtt网络编程,c#,wpf,开发语言,mqttnet服务器,mqttnet客户端,mqttnet搭建过程,mqtt通信

 2、测试订阅

C#MQTT编程07--MQTT服务器和客户端(wpf版),C#Mqtt网络编程,c#,wpf,开发语言,mqttnet服务器,mqttnet客户端,mqttnet搭建过程,mqtt通信

3、测试发布

 再启动一个客户端程序,有人不知道如何启动,看下面

C#MQTT编程07--MQTT服务器和客户端(wpf版),C#Mqtt网络编程,c#,wpf,开发语言,mqttnet服务器,mqttnet客户端,mqttnet搭建过程,mqtt通信

C#MQTT编程07--MQTT服务器和客户端(wpf版),C#Mqtt网络编程,c#,wpf,开发语言,mqttnet服务器,mqttnet客户端,mqttnet搭建过程,mqtt通信

c1发布一个消息,看看c1,c2有没有收到,很明显都收到了

C#MQTT编程07--MQTT服务器和客户端(wpf版),C#Mqtt网络编程,c#,wpf,开发语言,mqttnet服务器,mqttnet客户端,mqttnet搭建过程,mqtt通信

 服务器显示有关信息,完全good

C#MQTT编程07--MQTT服务器和客户端(wpf版),C#Mqtt网络编程,c#,wpf,开发语言,mqttnet服务器,mqttnet客户端,mqttnet搭建过程,mqtt通信

基于mqttnet实现的wpf版通信,完美实现,效果飞起来了,颜值高,效果好,帅B得上了飞机。

5、完整代码打包下载 

链接:https://pan.baidu.com/s/1sfQnGEEcsRTBKUSDOdCeTA 
提取码:z2hj 

讲解不易,分析不易,原创不易,整理不易,伙伴们动动你的金手指,你的支持是我最大的动力。

C#MQTT编程07--MQTT服务器和客户端(wpf版),C#Mqtt网络编程,c#,wpf,开发语言,mqttnet服务器,mqttnet客户端,mqttnet搭建过程,mqtt通信C#MQTT编程07--MQTT服务器和客户端(wpf版),C#Mqtt网络编程,c#,wpf,开发语言,mqttnet服务器,mqttnet客户端,mqttnet搭建过程,mqtt通信文章来源地址https://www.toymoban.com/news/detail-796921.html

到了这里,关于C#MQTT编程07--MQTT服务器和客户端(wpf版)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 手机、电脑mqtt客户端通过腾讯云服务器远程连接ESP32

            本文将实现:         1、esp32与腾讯云物联网服务器通过mqtt协议通信         2、电脑和手机客户端通过mqtt与腾讯云相通信         3、腾讯云服务器内部消息转发,将手机、电脑发布的主题转发给esp32订阅,实现手机、电脑与esp32的远程通信。      

    2024年02月11日
    浏览(62)
  • WPF真入门教程28--项目案例--MQTT服务器和客户端

    这个案例还是布局加视图模型,样式应用,业务逻辑,该项目是一个mqtt服务器和客户端的通信工具,这里不去分析mqtt的通信原理,关注在于wpf技能的应用,能够掌握这个例子,离项目开发也差不多了,只是没有跟db打交道,本项目重点在于理解mvvm模式,开发环境依然是vs20

    2024年01月17日
    浏览(58)
  • 网络编程六--UDP服务器客户端

    UDP(User Datagram Protocol)称为用户数据报协议,是一种无连接的传输协议。 UDP的主要应用在即使丢失部分数据,也不影响整体效果的场景。例实时传输视频或音频时,即使丢失部分数据,也不会影响整体效果,只是会有轻微的画面抖动或杂音。 UDP服务器/客户端不像TCP那样,交

    2024年02月15日
    浏览(49)
  • 【网络编程】实现UDP/TCP客户端、服务器

    需要云服务器等云产品来学习Linux的同学可以移步/--腾讯云--/--阿里云--/--华为云--/官网,轻量型云服务器低至112元/年,新用户首次下单享超低折扣。   目录 一、UDP 1、Linux客户端、服务器 1.1udpServer.hpp 1.2udpServer.cc 1.3udpClient.hpp 1.4udpClient.cc 1.5onlineUser.hpp 2、Windows客户端 二、T

    2024年02月06日
    浏览(61)
  • unix网络编程-简易服务器与客户端程序解析

    a -- address f -- file        eg: fputs() -- file put stream fd -- file descriptor h - host(主机) in/inet -- internet        eg: sockaddr_in; inet_aton n -- network(网络字节序)/numeric(数值) p -- protocol(协议)/presentation(表达/呈现形式) s -- socket        eg: sin -- socket internet t -- type,用于指定某种

    2024年01月16日
    浏览(69)
  • Python网络编程实战:构建TCP服务器与客户端

    Python网络编程实战:构建TCP服务器与客户端 在信息化时代,网络编程是软件开发中不可或缺的一部分。Python作为一种功能强大的编程语言,提供了丰富的网络编程库和工具,使得开发者能够轻松构建各种网络应用。本文将详细介绍如何在Python中进行网络编程,特别是如何使用

    2024年04月15日
    浏览(44)
  • C#实现简单TCP服务器和客户端网络编程

    在C#中进行网络编程涉及许多类和命名空间,用于创建和管理网络连接、传输数据等。下面是一些主要涉及的类和命名空间: System.Net 命名空间: 这个命名空间提供了大部分网络编程所需的类,包括: IPAddress :用于表示IP地址。 IPEndPoint :表示IP地址和端口号的组合。 Socke

    2024年02月11日
    浏览(63)
  • Linux网络编程:Socket服务器和客户端实现双方通信

    目录 一,什么是网络编程 二,为什么使用端口号 三,TCP协议与UDP协议 ①TCP(传输控制协议) ②UDP(用户数据报协议,User Data Protocol) ③总结归纳 四,Socket服务器和客户端的开发流程 五,服务器和客户端相关API说明 ①socket()函数 ②bind()函数 ③listen()函数 ④accept()函数 ⑤客户端

    2024年02月11日
    浏览(71)
  • 【网络编程】网络套接字&udp通用服务器和客户端

    端口号(port)是传输层协议的内容: 端口号是一个2字节16位的整数(uint16) 端口号用来标识主机上的一个进程 IP地址+port能够标识网络上的某一台主机和某一个进程 一个端口号只能被一个进程占用 此处我们先对TCP(Transmission Control Protocol 传输控制协议) 有一个直观的认识,后面再

    2024年02月16日
    浏览(214)
  • Socket网络编程(TCP/IP)实现服务器/客户端通信。

    一.前言 回顾之前进程间通信(无名管道,有名管道,消息队列,共享内存,信号,信号量),都是在同一主机由内核来完成的通信。 那不同主机间该怎么通信呢? 可以使用Socket编程来实现。 Socket编程可以通过网络来实现实现不同主机之间的通讯。 二.Socket编程的网络模型如

    2024年02月08日
    浏览(89)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包