点击或拖拽改变大小

MqttSyncClient 类

基于MQTT协议的同步访问的客户端程序,支持以同步的方式访问服务器的数据信息,并及时的反馈结果,当服务器启动文件功能时,也支持文件的上传,下载,删除操作等。
The client program based on MQTT protocol for synchronous access supports synchronous access to the server's data information and timely feedback of results, When the server starts the file function, it also supports file upload, download, and delete operations.
继承层次
SystemObject
  HslCommunication.Core.NetBinaryCommunication
    HslCommunication.Core.NetTcpNetCommunication
      HslCommunication.MQTTMqttSyncClient
        HslCommunication.MQTTMqttRpcDevice

命名空间:  HslCommunication.MQTT
程序集:  HslCommunication (在 HslCommunication.dll 中) 版本:12.1.2.0 (12.1.2.0)
语法
public class MqttSyncClient : TcpNetCommunication

MqttSyncClient 类型公开以下成员。

构造函数
  名称说明
公共方法MqttSyncClient(MqttConnectionOptions)
实例化一个MQTT的同步客户端
Instantiate an MQTT synchronization client
公共方法MqttSyncClient(IPAddress, Int32)
通过指定的ip地址及端口来实例化一个同步的MQTT客户端
Instantiate a synchronized MQTT client with the specified IP address and port
公共方法MqttSyncClient(String, Int32)
通过指定的ip地址及端口来实例化一个同步的MQTT客户端
Instantiate a synchronized MQTT client with the specified IP address and port
Top
属性
  名称说明
公共属性CommunicationPipe
获取或设置当前的管道信息,管道类型为CommunicationPipe的继承类,内置了PipeTcpNet管道,PipeUdpNet管道,PipeSerialPort管道等
(继承自 BinaryCommunication。)
公共属性ConnectionId
当前连接的唯一ID号,默认为长度20的guid码加随机数组成,方便列表管理,也可以自己指定
The unique ID number of the current connection. The default is a 20-digit guid code plus a random number.
(继承自 BinaryCommunication。)
公共属性ConnectionOptions
获取或设置当前的连接信息,客户端将根据这个连接配置进行连接服务器,在连接之前需要设置相关的信息才有效。
To obtain or set the current connection information, the client will connect to the server according to this connection configuration. Before connecting, the relevant information needs to be set to be effective.
公共属性代码示例ConnectTimeOut
获取或设置接收服务器反馈的时间,如果为负数,则不接收反馈
Gets or sets the time to receive server feedback, and if it is a negative number, does not receive feedback
(继承自 TcpNetCommunication。)
公共属性代码示例IpAddress
获取或是设置远程服务器的IP地址,如果是本机测试,那么需要设置为127.0.0.1
Get or set the IP address of the remote server. If it is a local test, then it needs to be set to 127.0.0.1
(继承自 TcpNetCommunication。)
公共属性LocalBinding
获取或设置绑定的本地的IP地址和端口号信息,如果端口设置为0,代表任何可用的端口
Get or set the bound local IP address and port number information, if the port is set to 0, it means any available port
(继承自 TcpNetCommunication。)
公共属性代码示例LogNet
组件的日志工具,支持日志记录,只要实例化后,当前网络的基本信息,就以DEBUG等级进行输出
The component's logging tool supports logging. As long as the instantiation of the basic network information, the output will be output at DEBUG
(继承自 BinaryCommunication。)
公共属性代码示例Port
获取或设置服务器的端口号,具体的值需要取决于对方的配置
Gets or sets the port number of the server. The specific value depends on the configuration of the other party.
(继承自 TcpNetCommunication。)
公共属性代码示例ReceiveTimeOut
获取或设置接收服务器反馈的时间,如果为负数,则不接收反馈
Gets or sets the time to receive server feedback, and if it is a negative number, does not receive feedback
(继承自 BinaryCommunication。)
公共属性SendBeforeHex
获取或设置在发送通信报文前追加发送的字节信息,HEX格式,通常用于lora组网时,需要携带 00 00 00 02 四个字节的站地址功能。
Obtain or set the byte information sent before sending communication packets, HEX format, usually used for LORA networking, you need to carry 00 00 00 02 four-byte station address function.
(继承自 BinaryCommunication。)
公共属性SleepTime
获取或设置在正式接收对方返回数据前的时候,需要休息的时间,当设置为0的时候,不需要休息。
Get or set the time required to rest before officially receiving the data from the other party. When it is set to 0, no rest is required.
(继承自 BinaryCommunication。)
公共属性SocketKeepAliveTime
获取或设置客户端的Socket的心跳时间信息,这个是Socket底层自动实现的心跳包,不基于协议层实现。默认小于0,不开启心跳检测,如果需要开启,设置 60_000 比较合适,单位毫秒
Get or set the heartbeat time information of the Socket of the client. This is the heartbeat packet automatically implemented by the bottom layer of the Socket, not based on the protocol layer. The default value is less than 0, and heartbeat detection is not enabled. If you need to enable it, it is more appropriate to set 60_000, in milliseconds.
(继承自 TcpNetCommunication。)
公共属性StringEncoding
获取或设置使用字符串访问的时候,使用的编码信息,默认为UT8编码
Get or set the encoding information used when accessing with a string, the default is UT8 encoding
Top
方法
  名称说明
公共方法代码示例ConnectClose
手动断开与远程服务器的连接,如果当前是长连接模式,那么就会切换到短连接模式
Manually disconnect from the remote server, if it is currently in long connection mode, it will switch to short connection mode
(继承自 TcpNetCommunication。)
公共方法代码示例ConnectCloseAsync
手动断开与远程服务器的连接,如果当前是长连接模式,那么就会切换到短连接模式
Manually disconnect from the remote server, if it is currently in long connection mode, it will switch to short connection mode
(继承自 TcpNetCommunication。)
公共方法代码示例ConnectServer
尝试连接远程的服务器,如果连接成功,就切换短连接模式到长连接模式,后面的每次请求都共享一个通道,使得通讯速度更快速
Try to connect to a remote server. If the connection is successful, switch the short connection mode to the long connection mode. Each subsequent request will share a channel, making the communication speed faster.
(继承自 TcpNetCommunication。)
公共方法代码示例ConnectServerAsync
尝试连接远程的服务器,如果连接成功,就切换短连接模式到长连接模式,后面的每次请求都共享一个通道,使得通讯速度更快速
Try to connect to a remote server. If the connection is successful, switch the short connection mode to the long connection mode. Each subsequent request will share a channel, making the communication speed faster.
(继承自 TcpNetCommunication。)
受保护的方法DecideWhetherQAMessage
决定当前的消息是否是用于问答机制返回的消息,默认直接返回 true, 实际的情况需要根据协议进行重写方法
To determine whether the current message is the message returned by the question answering mechanism, the default is true. In actual cases, the rewriting method needs to be performed according to the protocol
(继承自 BinaryCommunication。)
公共方法DeleteFile(String, String)
[文件引擎] 删除服务器的指定的文件名,需要指定分类信息,文件名
[File Engine] Delete the specified file name of the server, need to specify the classification information, file name
公共方法DeleteFile(String, String)
[文件引擎] 删除服务器的指定的文件名,需要指定分类信息,文件名
[File Engine] Delete the specified file name of the server, need to specify the classification information, file name
公共方法DeleteFileAsync(String, String)
[文件引擎] 删除服务器的指定的文件名,需要指定分类信息,文件名
[File Engine] Delete the specified file name of the server, need to specify the classification information, file name
公共方法DeleteFileAsync(String, String)
[文件引擎] 删除服务器的指定的文件名,需要指定分类信息,文件名
[File Engine] Delete the specified file name of the server, need to specify the classification information, file name
公共方法DeleteFolder
[文件引擎] 删除服务器上指定的分类信息及管理的所有的文件,包含所有的子分类信息,不可逆操作,谨慎操作。
[File Engine] Delete the specified classification information and all files managed on the server, including all sub-classification information, irreversible operation, and careful operation.
公共方法DeleteFolderAsync
[文件引擎] 删除服务器上指定的分类信息及管理的所有的文件,包含所有的子分类信息,不可逆操作,谨慎操作。
[File Engine] Delete the specified classification information and all files managed on the server, including all sub-classification information, irreversible operation, and careful operation.
公共方法DeleteFolderFiles
[文件引擎] 删除服务器上指定的分类的所有的文件,不可逆操作,谨慎操作。
[File Engine] Delete the specified classification information and all files managed on the server, irreversible operation, and careful operation.
公共方法DeleteFolderFilesAsync
[文件引擎] 删除服务器上指定的分类的所有的文件,不可逆操作,谨慎操作。
[File Engine] Delete the specified classification information and all files managed on the server, irreversible operation, and careful operation.
公共方法DownloadBitmap
[文件引擎] 从远程服务器下载一个文件,生成一个Bitmap图片对象,需要指定文件类别,文件名,进度报告,可用于用户头像的存储
[File Engine] Download a file from a remote server and generate a Bitmap image object. You need to specify the file category, file name, and progress report, which can be used to store the user's avatar
公共方法DownloadBitmapAsync
[文件引擎] 从远程服务器下载一个文件,生成一个Bitmap图片对象,需要指定文件类别,文件名,进度报告,可用于用户头像的存储
[File Engine] Download a file from a remote server and generate a Bitmap image object. You need to specify the file category, file name, and progress report, which can be used to store the user's avatar
公共方法DownloadFile(String, String, ActionInt64, Int64, Stream, HslCancelToken)
[文件引擎] 从远程服务器下载一个文件到流中,需要指定文件类别,文件名,进度报告,本地保存的文件名
To download a file from a remote server to the stream, you need to specify the file category, file name, progress report, and file name saved locally
公共方法DownloadFile(String, String, ActionInt64, Int64, String, HslCancelToken)
[文件引擎] 从远程服务器下载一个文件到本地,需要指定文件类别,文件名,进度报告,本地保存的文件名
[File Engine] To download a file from a remote server to the local, you need to specify the file category, file name, progress report, and file name saved locally
公共方法DownloadFileAsync(String, String, ActionInt64, Int64, Stream, HslCancelToken)
[文件引擎] 从远程服务器下载一个文件到流中,需要指定文件类别,文件名,进度报告,本地保存的文件名
To download a file from a remote server to the stream, you need to specify the file category, file name, progress report, and file name saved locally
公共方法DownloadFileAsync(String, String, ActionInt64, Int64, String, HslCancelToken)
[文件引擎] 从远程服务器下载一个文件到本地,需要指定文件类别,文件名,进度报告,本地保存的文件名
[File Engine] To download a file from a remote server to the local, you need to specify the file category, file name, progress report, and file name saved locally
公共方法DownloadPathFileNames
[文件引擎] 下载指定分类信息的所有的文件描述信息,需要指定分类信息,例如:Files/Personal/Admin
[File Engine] To download all the file description information of the specified classification information, you need to specify the classification information, for example: Files/Personal/Admin
公共方法DownloadPathFileNamesAsync
[文件引擎] 下载指定分类信息的所有的文件描述信息,需要指定分类信息,例如:Files/Personal/Admin
[File Engine] To download all the file description information of the specified classification information, you need to specify the classification information, for example: Files/Personal/Admin
公共方法DownloadPathFolders
下载指定分类信息的全部子分类信息
Download all sub-category information of the specified category information
公共方法DownloadPathFoldersAsync
下载指定分类信息的全部子分类信息
Download all sub-category information of the specified category information
公共方法Equals
Determines whether the specified object is equal to the current object.
(继承自 Object。)
受保护的方法ExtraAfterReadFromCoreServer
和服务器交互完成的时候调用的方法,可以根据读写结果进行一些额外的操作,具体的操作需要根据实际的需求来重写实现
The method called when the interaction with the server is completed can perform some additional operations based on the read and write results. The specific operations need to be rewritten according to actual needs.
(继承自 BinaryCommunication。)
受保护的方法代码示例ExtraOnDisconnect
根据实际的协议选择是否重写本方法,有些协议在断开连接之前,需要发送一些报文来关闭当前的网络通道
Select whether to rewrite this method according to the actual protocol. Some protocols need to send some packets to close the current network channel before disconnecting.
(继承自 BinaryCommunication。)
受保护的方法代码示例ExtraOnDisconnectAsync
根据实际的协议选择是否重写本方法,有些协议在断开连接之前,需要发送一些报文来关闭当前的网络通道
Select whether to rewrite this method according to the actual protocol. Some protocols need to send some packets to close the current network channel before disconnecting.
(继承自 BinaryCommunication。)
受保护的方法Finalize
Allows an object to try to free resources and perform other cleanup operations before it is reclaimed by garbage collection.
(继承自 Object。)
公共方法GetGroupFileInfo
[文件引擎] 获取服务器文件夹的指定目录的文件统计信息,包括文件数量,总大小,最后更新时间
[File Engine] Get the file statistics of the specified directory of the server folder, including the number of files, the total size, and the last update time
公共方法GetGroupFileInfoAsync
[文件引擎] 获取服务器文件夹的指定目录的文件统计信息,包括文件数量,总大小,最后更新时间
[File Engine] Get the file statistics of the specified directory of the server folder, including the number of files, the total size, and the last update time
公共方法GetHashCode
Serves as the default hash function.
(继承自 Object。)
受保护的方法GetLogTextFromBinary
获取当前的报文进行日志记录的时候,是否使用二进制的格式记录,默认返回 LogMsgFormatBinary,重写可以根据session对象分别返回不同记录模式
Whether to log the current packet in binary format, the default return is LogMsgFormatBinary. If you want to override it, different recording modes can be returned according to session
(继承自 BinaryCommunication。)
受保护的方法GetNewNetMessage
获取一个新的消息对象的方法,需要在继承类里面进行重写
The method to get a new message object needs to be overridden in the inheritance class
(继承自 BinaryCommunication。)
公共方法GetSubGroupFileInfos
[文件引擎] 获取服务器文件夹的指定目录的所有子目录的文件信息,包括每个子目录的文件数量,总大小,最后更新时间
[File Engine] Get the file information of all subdirectories of the specified directory of the server folder, including the number of files in each subdirectory, the total size, and the last update time
公共方法GetSubGroupFileInfosAsync
[文件引擎] 获取服务器文件夹的指定目录的所有子目录的文件信息,包括每个子目录的文件数量,总大小,最后更新时间
[File Engine] Get the file information of all subdirectories of the specified directory of the server folder, including the number of files in each subdirectory, the total size, and the last update time
公共方法GetType
Gets the Type of the current instance.
(继承自 Object。)
受保护的方法代码示例InitializationOnConnect
根据实际的协议选择是否重写本方法,有些协议在创建连接之后,需要进行一些初始化的信号握手,才能最终建立网络通道。
Whether to rewrite this method is based on the actual protocol. Some protocols require some initial signal handshake to establish a network channel after the connection is created.
(重写 BinaryCommunicationInitializationOnConnect.)
受保护的方法代码示例InitializationOnConnectAsync
根据实际的协议选择是否重写本方法,有些协议在创建连接之后,需要进行一些初始化的信号握手,才能最终建立网络通道。
Whether to rewrite this method is based on the actual protocol. Some protocols require some initial signal handshake to establish a network channel after the connection is created.
(重写 BinaryCommunicationInitializationOnConnectAsync.)
公共方法IpAddressPing
对当前设备的IP地址进行PING的操作,返回PING的结果,正常来说,返回Success
PING the IP address of the current device and return the PING result. Normally, it returns Success
(继承自 TcpNetCommunication。)
公共方法IsFileExists
[文件引擎] 请求服务器指定分类是否存在指定的文件名,需要指定分类信息,文件名
[File Engine] Request the server to specify whether the specified file name exists in the specified category, need to specify the category information, file name
公共方法IsFileExistsAsync
[文件引擎] 请求服务器指定分类是否存在指定的文件名,需要指定分类信息,文件名
[File Engine] Request the server to specify whether the specified file name exists in the specified category, need to specify the category information, file name
受保护的方法LogRevcMessage(Byte)
使用日志记录一个接收的报文信息
` Logs are used to record information about a received packet
(继承自 BinaryCommunication。)
受保护的方法LogRevcMessage(Byte, PipeSession)
使用日志记录一个接收的报文信息
` Logs are used to record information about a received packet
(继承自 BinaryCommunication。)
受保护的方法LogSendMessage(Byte)
使用日志记录一个发送的报文信息
Logs are used to record information about a send packet
(继承自 BinaryCommunication。)
受保护的方法LogSendMessage(Byte, PipeSession)
使用日志记录一个发送的报文信息
Logs are used to record information about a send packet
(继承自 BinaryCommunication。)
受保护的方法MemberwiseClone
Creates a shallow copy of the current Object.
(继承自 Object。)
公共方法PackCommandWithHeader
对当前的命令进行打包处理,通常是携带命令头内容,标记当前的命令的长度信息,需要进行重写,否则默认不打包
The current command is packaged, usually carrying the content of the command header, marking the length of the current command, and it needs to be rewritten, otherwise it is not packaged by default
(继承自 BinaryCommunication。)
公共方法Read
从MQTT服务器同步读取数据,将payload发送到服务器,然后从服务器返回相关的数据,支持数据发送进度报告,服务器执行进度报告,接收数据进度报告操作
Synchronously read data from the MQTT server, send the payload to the server, and then return relevant data from the server, support data transmission progress report, the server executes the progress report, and receives the data progress report
公共方法ReadAsync
从MQTT服务器同步读取数据,将payload发送到服务器,然后从服务器返回相关的数据,支持数据发送进度报告,服务器执行进度报告,接收数据进度报告操作
Synchronously read data from the MQTT server, send the payload to the server, and then return relevant data from the server, support data transmission progress report, the server executes the progress report, and receives the data progress report
公共方法代码示例ReadFromCoreServer(Byte)
将二进制的数据发送到管道中去,然后从管道里接收二进制的数据回来,并返回是否成功的结果对象。
Send binary data to the pipeline, and then receive binary data back from the pipeline, and return whether the success of the result object
(继承自 BinaryCommunication。)
公共方法ReadFromCoreServer(IEnumerableByte) (继承自 BinaryCommunication。)
公共方法代码示例ReadFromCoreServer(Byte, Boolean, Boolean)
将二进制的数据发送到管道中去,然后从管道里接收二进制的数据回来,并返回是否成功的结果对象。
Send binary data to the pipeline, and then receive binary data back from the pipeline, and return whether the success of the result object
(继承自 BinaryCommunication。)
公共方法ReadFromCoreServer(CommunicationPipe, Byte, Boolean, Boolean)
使用指定的管道来进行数据通信,发送原始数据到管道,然后从管道接收相关的数据返回,本方法无锁
(重写 BinaryCommunicationReadFromCoreServer(CommunicationPipe, Byte, Boolean, Boolean).)
公共方法代码示例ReadFromCoreServerAsync(Byte)
将二进制的数据发送到管道中去,然后从管道里接收二进制的数据回来,并返回是否成功的结果对象。
Send binary data to the pipeline, and then receive binary data back from the pipeline, and return whether the success of the result object
(继承自 BinaryCommunication。)
公共方法ReadFromCoreServerAsync(IEnumerableByte) (继承自 BinaryCommunication。)
公共方法代码示例ReadFromCoreServerAsync(Byte, Boolean, Boolean)
将二进制的数据发送到管道中去,然后从管道里接收二进制的数据回来,并返回是否成功的结果对象。
Send binary data to the pipeline, and then receive binary data back from the pipeline, and return whether the success of the result object
(继承自 BinaryCommunication。)
公共方法ReadFromCoreServerAsync(CommunicationPipe, Byte, Boolean, Boolean)
使用指定的管道来进行数据通信,发送原始数据到管道,然后从管道接收相关的数据返回,本方法无锁
(重写 BinaryCommunicationReadFromCoreServerAsync(CommunicationPipe, Byte, Boolean, Boolean).)
公共方法ReadRetainTopics
读取服务器的已经驻留的所有消息的主题列表
Read the topic list of all messages that have resided on the server
公共方法ReadRetainTopicsAsync
读取服务器的已经驻留的所有消息的主题列表
Read the topic list of all messages that have resided on the server
公共方法ReadRpcT(String, Object)
读取MQTT服务器注册的RPC接口,忽略返回的Topic数据,直接将结果转换为泛型对象,如果JSON转换失败,将返回错误,参数传递主题和数据负载, 数据负载示例:new { address = "", length = 0 } 本质是一个匿名对象。
Read the RPC interface registered by the MQTT server, ignore the returned Topic data, and directly convert the result into a generic object. If the JSON conversion fails, an error will be returned. The parameter passes the topic and the data payload. The data payload example: new { address = "", length = 0 } is essentially an anonymous object.
公共方法ReadRpcT(String, String)
读取MQTT服务器注册的RPC接口,忽略返回的Topic数据,直接将结果转换为泛型对象,如果JSON转换失败,将返回错误,参数传递主题和数据负载, 数据负载示例:"{\"address\": \"100\",\"length\": 10}" 本质是一个字符串。
Read the RPC interface registered by the MQTT server, ignore the returned Topic data, and directly convert the result into a generic object. If the JSON conversion fails, an error will be returned. The parameter passes the topic and the data payload. The data payload example: "{\"address\ ": \"100\",\"length\": 10}" is essentially a string.
公共方法ReadRpcApiLog
读取服务器的指定的API接口的每天的调用次数,如果API接口不存在,或是还没有调用数据,则返回失败。
Read the number of calls per day of the designated API interface of the server. If the API interface does not exist or the data has not been called yet, it returns a failure.
公共方法ReadRpcApiLogAsync
读取服务器的指定的API接口的每天的调用次数,如果API接口不存在,或是还没有调用数据,则返回失败。
Read the number of calls per day of the designated API interface of the server. If the API interface does not exist or the data has not been called yet, it returns a failure.
公共方法ReadRpcApis
读取服务器的已经注册的API信息列表,将返回API的主题路径,注释信息,示例的传入的数据信息。
Read the registered API information list of the server, and return the API subject path, annotation information, and sample incoming data information.
公共方法ReadRpcApisAsync
读取服务器的已经注册的API信息列表,将返回API的主题路径,注释信息,示例的传入的数据信息。
Read the registered API information list of the server, and return the API subject path, annotation information, and sample incoming data information.
公共方法ReadRpcAsyncT(String, Object)
读取MQTT服务器注册的RPC接口,忽略返回的Topic数据,直接将结果转换为泛型对象,如果JSON转换失败,将返回错误,参数传递主题和数据负载, 数据负载示例:new { address = "", length = 0 } 本质是一个匿名对象。
Read the RPC interface registered by the MQTT server, ignore the returned Topic data, and directly convert the result into a generic object. If the JSON conversion fails, an error will be returned. The parameter passes the topic and the data payload. The data payload example: new { address = "", length = 0 } is essentially an anonymous object.
公共方法ReadRpcAsyncT(String, String)
读取MQTT服务器注册的RPC接口,忽略返回的Topic数据,直接将结果转换为泛型对象,如果JSON转换失败,将返回错误,参数传递主题和数据负载, 数据负载示例:"{\"address\": \"100\",\"length\": 10}" 本质是一个字符串。
Read the RPC interface registered by the MQTT server, ignore the returned Topic data, and directly convert the result into a generic object. If the JSON conversion fails, an error will be returned. The parameter passes the topic and the data payload. The data payload example: "{\"address\ ": \"100\",\"length\": 10}" is essentially a string.
公共方法ReadSessions
读取服务器里当前的会话信息
公共方法ReadString
从MQTT服务器同步读取数据,将指定编码的字符串payload发送到服务器,然后从服务器返回相关的数据,并转换为指定编码的字符串,支持数据发送进度报告,服务器执行进度报告,接收数据进度报告操作
Synchronously read data from the MQTT server, send the specified encoded string payload to the server, and then return the data from the server, and convert it to the specified encoded string, support data transmission progress report, the server executes the progress report, and receives the data progress report
公共方法ReadStringAsync
从MQTT服务器同步读取数据,将指定编码的字符串payload发送到服务器,然后从服务器返回相关的数据,并转换为指定编码的字符串,支持数据发送进度报告,服务器执行进度报告,接收数据进度报告操作
Synchronously read data from the MQTT server, send the specified encoded string payload to the server, and then return the data from the server, and convert it to the specified encoded string, support data transmission progress report, the server executes the progress report, and receives the data progress report
公共方法ReadTopicPayload
读取服务器的已经驻留的指定主题的消息内容
Read the topic list of all messages that have resided on the server
公共方法ReadTopicPayloadAsync
读取服务器的已经驻留的指定主题的消息内容
Read the topic list of all messages that have resided on the server
公共方法RenameFolder
[文件引擎] 重命名服务器上指定的路径信息,需要指定新的路径名称,当新的路径已经存在的时候,命名失败。
[File Engine] Renames the specified path information on the server, you need to specify a new path name, and when the new path already exists, the naming fails.
公共方法RenameFolderAsync
[文件引擎] 重命名服务器上指定的路径信息,需要指定新的路径名称,当新的路径已经存在的时候,命名失败。
[File Engine] Renames the specified path information on the server, you need to specify a new path name, and when the new path already exists, the naming fails.
公共方法SetDtuPipe
将当前的通信对象设置DTU模式,允许传入现成的管道,并返回初始化结果,如果该设备重写了握手报文,就是返回握手结果
Set the current communication object to DTU mode, allow the existing pipe to be passed in, and return the initialization result, if the device rewrites the handshake packet, the handshake result is returned
(继承自 BinaryCommunication。)
公共方法SetDtuPipeAsync
将当前的通信对象设置DTU模式,允许传入现成的管道,并返回初始化结果,如果该设备重写了握手报文,就是返回握手结果
Set the current communication object to DTU mode, allow the existing pipe to be passed in, and return the initialization result, if the device rewrites the handshake packet, the handshake result is returned
(继承自 BinaryCommunication。)
公共方法ToString
Returns a string that represents the current object.
(重写 TcpNetCommunicationToString.)
公共方法UnpackResponseContent
根据对方返回的报文命令,对命令进行基本的拆包,例如各种Modbus协议拆包为统一的核心报文,还支持对报文的验证
According to the message command returned by the other party, the command is basically unpacked, for example, various Modbus protocols are unpacked into a unified core message, and the verification of the message is also supported
(继承自 BinaryCommunication。)
公共方法UploadFile(String, String, String, ActionInt64, Int64, HslCancelToken)
[文件引擎] 上传文件给服务器,需要指定上传文件的路径信息(服务器保存的名称就是文件名),以及上传到服务器的分类信息,支持进度汇报功能。
[File Engine] To upload a file to the server, you need to specify the path information of the uploaded file (the name saved by the server is the file name), as well as the classification information uploaded to the server, to support the progress report function.
公共方法UploadFile(Bitmap, String, String, String, ActionInt64, Int64, HslCancelToken)
[文件引擎] 上传一个Bitmap图片对象到服务器指定的分类下面,需要指定分类信息,服务器保存的文件名,描述信息,支持进度报告
[File Engine] Upload a Bitmap image object to the category specified by the server, you need to specify the category information, the file name saved by the server, description information, and support for progress reports
公共方法UploadFile(Stream, String, String, String, ActionInt64, Int64, HslCancelToken)
[文件引擎] 上传流给服务器,需要指定流,服务器保存的名字,以及上传到服务器的分类信息,支持进度汇报功能。
[File Engine] To upload a stream to the server, you need to specify the stream, the name saved by the server, and the classification information uploaded to the server to support the progress reporting function.
公共方法UploadFile(String, String, String, String, ActionInt64, Int64, HslCancelToken)
[文件引擎] 上传文件给服务器,需要指定上传文件的路径信息,服务器保存的名字,以及上传到服务器的分类信息,支持进度汇报功能。
[File Engine] To upload a file to the server, you need to specify the path information of the uploaded file, the name saved by the server, and the classification information uploaded to the server to support the progress report function.
公共方法UploadFileAsync(String, String, String, ActionInt64, Int64, HslCancelToken)
[文件引擎] 上传文件给服务器,需要指定上传文件的路径信息(服务器保存的名称就是文件名),以及上传到服务器的分类信息,支持进度汇报功能。
[File Engine] To upload a file to the server, you need to specify the path information of the uploaded file (the name saved by the server is the file name), as well as the classification information uploaded to the server, to support the progress report function.
公共方法UploadFileAsync(Bitmap, String, String, String, ActionInt64, Int64, HslCancelToken)
[文件引擎] 上传一个Bitmap图片对象到服务器指定的分类下面,需要指定分类信息,服务器保存的文件名,描述信息,支持进度报告
[File Engine] Upload a Bitmap image object to the category specified by the server, you need to specify the category information, the file name saved by the server, description information, and support for progress reports
公共方法UploadFileAsync(Stream, String, String, String, ActionInt64, Int64, HslCancelToken)
[文件引擎] 上传流给服务器,需要指定流,服务器保存的名字,以及上传到服务器的分类信息,支持进度汇报功能。
[File Engine] To upload a stream to the server, you need to specify the stream, the name saved by the server, and the classification information uploaded to the server to support the progress reporting function.
公共方法UploadFileAsync(String, String, String, String, ActionInt64, Int64, HslCancelToken)
[文件引擎] 上传文件给服务器,需要指定上传文件的路径信息,服务器保存的名字,以及上传到服务器的分类信息,支持进度汇报功能。
[File Engine] To upload a file to the server, you need to specify the path information of the uploaded file, the name saved by the server, and the classification information uploaded to the server to support the progress report function.
Top
字段
  名称说明
受保护的字段LogMsgFormatBinary
设置日志记录报文是否二进制,如果为False,那就使用ASCII码
Set whether the log message is binary, if it is False, then use ASCII code
(继承自 BinaryCommunication。)
Top
扩展方法
  名称说明
公共扩展器方法ToJsonString
获取当前对象的JSON格式表示的字符串。
Gets the string represented by the JSON format of the current object.
(由 HslExtension 定义。)
Top
备注
在最新的V10.2.0及以上版本中,本客户端支持加密模式,启用加密模式后,就无法通过抓包的报文来分析出用户名密码,以及通信的数据细节,详细可以参考API文档。
示例
简单的实例化
// 简单的实例化例子
MqttSyncClient mqttSyncClient = new MqttSyncClient( new MqttConnectionOptions( )
{
    ClientId = "ABC",                     // 客户端的唯一的ID信息
    IpAddress = "127.0.0.1",              // 服务器的地址
} );
带用户名密码的实例化
// 如果有密码的情况
MqttSyncClient mqttSyncClient = new MqttSyncClient( new MqttConnectionOptions( )
{
    ClientId = "ABC",                                            // 客户端的唯一的ID信息
    IpAddress = "127.0.0.1",                                     // 服务器的地址
    Credentials = new MqttCredential( "admin", "123456" )        // 设置了用户名和密码
} );
连接示例
// 连接服务器
MqttSyncClient mqttSyncClient = new MqttSyncClient( new MqttConnectionOptions( )
{
    ClientId = "ABC",                     // 客户端的唯一的ID信息
    IpAddress = "127.0.0.1",              // 服务器的地址
} );
HslCommunication.OperateResult connect = mqttSyncClient.ConnectServer( );
if (connect.IsSuccess)
{
    // 连接成功
}
else
{
    // 连接失败,过会就需要重新连接了
}

// 关闭的话
mqttSyncClient.ConnectClose( );
读取数据示例
MqttSyncClient mqttSyncClient = new MqttSyncClient( new MqttConnectionOptions( )
{
    ClientId = "ABC",                     // 客户端的唯一的ID信息
    IpAddress = "127.0.0.1",              // 服务器的地址
} );

// 设置长连接
// mqttSyncClient.SetPersistentConnection( );

// 读取服务器的数据示例
HslCommunication.OperateResult<string, byte[]> read = mqttSyncClient.Read( topic: "A", payload: Encoding.UTF8.GetBytes( "测试数据" ) );
if (read.IsSuccess)
{
    // 读取成功
    string topic = read.Content1;
    byte[] payload = read.Content2;
}
else
{
    // 读取失败
}

// 你只需要负责不停的读取就好了,单次读取数据限制为200多M,如果网络异常,会自动重新连接的。
// 如果你的服务器都是按照字符串来处理的话,那么客户端可以简便代码,客户端默认采用UTF8编码,当然也可以自己指定
HslCommunication.OperateResult<string, string> read2 = mqttSyncClient.ReadString( "A", "测试数据" );
if (read2.IsSuccess)
{
    // 读取成功
    string topic = read2.Content1;
    string payload = read2.Content2;
}
else
{
    // 读取失败
}
带进度报告示例
MqttSyncClient mqttSyncClient = new MqttSyncClient( new MqttConnectionOptions( )
{
    ClientId = "ABC",                     // 客户端的唯一的ID信息
    IpAddress = "127.0.0.1",              // 服务器的地址
} );

// 设置长连接
// mqttSyncClient.SetPersistentConnection( );

// 读取服务器的时候进行进度报告,主要分为上传进度和下载进度,此处就简单的显示下而已
Action<long, long> uploadProgress = new Action<long, long>( ( already, total ) =>
 {
     Console.WriteLine( $"已发送:{(already * 100 / total)}%    已发送/总字节:{already}/{total}" );
 } );
Action<long, long> downloadProgress = new Action<long, long>( ( already, total ) =>
{
    Console.WriteLine( $"已下载:{(already * 100 / total)}%    已下载/总字节:{already}/{total}" );
} );
HslCommunication.OperateResult<string, byte[]> read = mqttSyncClient.Read( topic: "A", payload: Encoding.UTF8.GetBytes( "测试数据" ), uploadProgress, null, downloadProgress );
if (read.IsSuccess)
{
    // 读取成功
    string topic = read.Content1;
    byte[] payload = read.Content2;
}
else
{
    // 读取失败
}

// 你只需要负责不停的读取就好了,单次读取数据限制为200多M,如果网络异常,会自动重新连接的。

// 还有一种更复杂的情况,需要配合服务器侧来完成,现在假设一种情况,客户端向服务器发送一个命令,
// 然后服务器执行相关的操作,这个操作分为5个小操作,时间1-5秒不等,然后处理好后将结果发送给客户端
Action<string, string> handleProgress = new Action<string, string>( ( topic, msg ) =>
{
    // topic服务器可以存放处理进度
    Console.WriteLine( $"已完成:{topic}%    当前正在执行:{msg}" );
} );
HslCommunication.OperateResult<string, byte[]> read2 = mqttSyncClient.Read( topic: "B", payload: Encoding.UTF8.GetBytes( "测试数据" ), null, handleProgress, null );
if (read2.IsSuccess)
{
    // 读取成功
    string topic = read.Content1;
    byte[] payload = read.Content2;
}
else
{
    // 读取失败
}
当MqttServer注册了远程RPC接口的时候,例如将一个plc对象注册是接口对象,或是自定义的接口内容
RPC接口读取
MqttSyncClient mqttSyncClient = new MqttSyncClient( new MqttConnectionOptions( )
{
    ClientId = "ABC",                     // 客户端的唯一的ID信息
    IpAddress = "127.0.0.1",              // 服务器的地址
} );

// 设置长连接
// mqttSyncClient.SetPersistentConnection( );

// 最原始的读取,假设服务器注册了一个PLC的读写接口
OperateResult<string, string> read1 = mqttSyncClient.ReadString( "MainPLC/ReadBool", "{ \"address\": \"M300.1\" }" );
if (read1.IsSuccess)
{
    // read1.Content2 就是内容,bool值的json格式,true/false
}

// 下面是精简的读法
OperateResult<bool> read2 = mqttSyncClient.ReadRpc<bool>( "MainPLC/ReadBool", new { address = "M300.1" } );
if (read2.IsSuccess)
{
    // read2.Content 就是值,自动转换好bool值
}

// 读取的类型和服务器注册RPC接口的返回类型需要一致
服务器都有什么RPC接口呢?可以通过下面的方式知道
RPC接口列表
MqttSyncClient mqttSyncClient = new MqttSyncClient( new MqttConnectionOptions( )
{
    ClientId = "ABC",                     // 客户端的唯一的ID信息
    IpAddress = "127.0.0.1",              // 服务器的地址
} );

// 设置长连接
// mqttSyncClient.SetPersistentConnection( );

// 读取服务器的已经注册的API信息列表,将返回API的主题路径,注释信息,示例的传入的数据信息。
OperateResult<MqttRpcApiInfo[]> read1 = mqttSyncClient.ReadRpcApis( );
if (read1.IsSuccess)
{
    foreach (MqttRpcApiInfo rpcInfo in read1.Content)
    {
        Console.WriteLine( "Api: " + rpcInfo.ApiTopic );
        Console.WriteLine( "Description: " + rpcInfo.Description );
        Console.WriteLine( "" );
    }
}

// 使用完之后
mqttSyncClient.ConnectClose( );
关于加密模式,在不加密的情况下,用户名及密码,还有请求的数据信息会被第三方软件窃取,从而泄露一些关键的数据信息,如果使用了HslCommunicationV10.2.0版本以上创建的MQTTServer, 那么可以在客户端使用加密模式,加密使用RSA+AES混合加密,密钥动态生成,在保证效率的同时,具有很高的安全性。客户端使用加密如下:
加密举例
MqttSyncClient mqttSyncClient = new MqttSyncClient( new MqttConnectionOptions( )
{
    ClientId = "ABC",                     // 客户端的唯一的ID信息
    IpAddress = "127.0.0.1",              // 服务器的地址
    UseRSAProvider = true,                // 使用加密访问,上下传文件时也通用适用加密
} );

// 设置长连接
// mqttSyncClient.SetPersistentConnection( );

OperateResult<bool> read2 = mqttSyncClient.ReadRpc<bool>( "MainPLC/ReadBool", new { address = "M300.1" } );
if (read2.IsSuccess)
{
    // read2.Content 就是值,自动转换好bool值
}

// 使用完之后
mqttSyncClient.ConnectClose( );
下面演示文件部分的功能的接口方法,主要包含,上传,下载,删除,遍历操作
下载文件功能
MqttSyncClient mqttSyncClient = new MqttSyncClient( new MqttConnectionOptions( )
{
    ClientId = "ABC",                     // 客户端的唯一的ID信息
    IpAddress = "127.0.0.1",              // 服务器的地址
} );

// 下载文件的进度报告,此处就简单的打印出来而已
Action<long, long> downloadProgress = new Action<long, long>( ( already, total ) =>
{
    Console.WriteLine( $"已下载:{already * 100 / total}%    已下载/总字节:{already}/{total}" );
} );

// 此处演示下载服务器的一个文件,需要这个文件在服务器存在,并且,账户密码,文件操作在服务器验证通过,最终才会下载成功
// groups 参数是文件的分类目录信息,同一目录不允许存在同名文件
HslCommunication.OperateResult download = mqttSyncClient.DownloadFile( "Files/Group/Admin", "123.txt", downloadProgress, "D:\\123.txt" );
if (download.IsSuccess)
{
    // 下载成功,在D盘目录查看
}
else
{
    // 下载失败
    Console.WriteLine( "Download failed, reason:" + download.Message );
}
在实际的窗体界面开发中,会更加的复杂,有个按钮点击下载,还需要支持取消下载操作。可以参考如下的代码:
带取消的下载功能
// mqttSyncClient 即为通信对象

private HslCancelToken downloadCacel = null;

private async void button_download_Click( object sender, EventArgs e )
{
    // 点击开始下载,此处按照实际项目需求放到了后台线程处理,事实上这种耗时的操作就应该放到后台线程
    // click this button to start a backgroud thread for downloading file
    downloadCacel = new HslCancelToken( );
    await DownloadFileExample( );
    downloadCacel = null;
}

/*************************************************************************************************
 * 
 *   一条指令即可完成文件的下载操作,下载模式有三种
 *   1. 指定需要下载的文件名(带后缀)
 *   2. 将服务器上的数据下载到流(stream)中
 *   3. 将服务器上的数据下载到bitmap图片中
 * 
 ********************************************************************************************/

private async Task DownloadFileExample( )
{
    progressBar2.Value = 0;                                       // 下载的进度条复位
    button_download.Enabled = false;                              // 下载按钮禁止,打开取消下载按钮
    button_download_cancel.Enabled = true;
    label15.Text = "Start downloading...";

    string fileName = textBox_download_fileName.Text;
    DateTime downloadStartTime = DateTime.Now;
    OperateResult result = await mqttSyncClient.DownloadFileAsync(
            textBox5.Text,                                         // 类别信息,例如 Files/Personal/Admin
            fileName,                                              // 文件在服务器上保存的名称,举例123.txt
            DownloadReportProgress,                                // 文件下载的时候的进度报告,友好的提示下载进度信息
            Application.StartupPath + @"\Files\" + fileName,       // 下载后在文本保存的路径,也可以直接下载到 MemoryStream 的数据流中,或是bitmap中,或是手动选择存储路径
            downloadCacel                                          // 取消下载操作的令牌,如果不需要取消,使用NULL即可
            );

    button_download.Enabled = true;
    button_download_cancel.Enabled = false;
    if (result.IsSuccess)
    {
        // message: file download success
        label15.Text = "文件下载成功!耗时:" + (DateTime.Now - downloadStartTime).TotalSeconds.ToString( "F1" ) + " 秒";
    }
    else
    {
        // 失败原因多半来自网络异常,还有文件不存在,分类名称填写异常
        // mostly failed by network exception, like offline, and file not exsist,
        label15.Text = "文件下载失败:" + result.Message;
    }
}

// 点击下载取消的按钮,取消的令牌设置为 True
private void button_download_cancel_Click( object sender, EventArgs e )
{
    if (downloadCacel != null) downloadCacel.IsCancelled = true;
}

/// <summary>
/// 用于更新文件下载进度的方法,该方法是线程安全的,主要作用是将下载文件的进度在进度条上显示
/// </summary>
/// <param name="receive">已经接收的字节数</param>
/// <param name="totle">总字节数</param>
private void DownloadReportProgress( long receive, long totle )
{
    if (progressBar2.InvokeRequired)
    {
        progressBar2.Invoke( new Action<long, long>( DownloadReportProgress ), receive, totle );
        return;
    }

    // 此处代码是线程安全的
    // thread-safe code
    int value = (int)(receive * 100L / totle);
    progressBar2.Value = value;
    label9.Text = SoftBasic.GetSizeDescription( receive ) + "/" + SoftBasic.GetSizeDescription( totle );
}
上传文件功能
MqttSyncClient mqttSyncClient = new MqttSyncClient( new MqttConnectionOptions( )
{
    ClientId = "ABC",                     // 客户端的唯一的ID信息
    IpAddress = "127.0.0.1",              // 服务器的地址
} );

// 下载文件的进度报告,此处就简单的打印出来而已
Action<long, long> uploadProgress = new Action<long, long>( ( already, total ) =>
{
    Console.WriteLine( $"已上传:{already * 100 / total}%    已下载/总字节:{already}/{total}" );
} );

// 此处演示上传服务器的一个文件,需要这个文件在本地存在,并且,账户密码,文件操作在服务器验证通过,最终才会上传成功
// groups 参数是文件的分类目录信息,同一目录不允许存在同名文件
HslCommunication.OperateResult upload = mqttSyncClient.UploadFile( "D:\\123.txt", "Files/Group/Admin", "这是一个文件的注释,可由可无", uploadProgress );
if (upload.IsSuccess)
{
    // 上传成功,就可以下载了
}
else
{
    // 下载失败
    Console.WriteLine( "Upload failed, reason:" + upload.Message );
}
在实际的窗体界面开发中,会更加的复杂,有个按钮点击上传,还需要支持取消上传操作。可以参考如下的代码:
带取消的上传功能
/*************************************************************************************************
 * 
 *   一条指令即可完成文件的上传操作,上传模式有三种
 *   1. 指定本地的完整路径的文件名
 *   2. 将流(stream)中的数据上传到服务器
 *   3. 将bitmap图片数据上传到服务器
 * 
 ********************************************************************************************/

// 取消上传的令牌
private HslCancelToken uploadCacel = null;
// mqttSyncClient 即为通信对象

private async void button_upload_Click( object sender, EventArgs e )
{
    // 开始上传
    uploadCacel = new HslCancelToken( );
    if (!string.IsNullOrEmpty( textBox3.Text ))
    {
        if (!System.IO.File.Exists( textBox3.Text ))
        {
            MessageBox.Show( "选择的文件不存在,退出!" );
            return;
        }

        DateTime uploadStartTime = DateTime.Now;
        OperateResult result = await UploadFlieExample( string.Empty );

        if (result.IsSuccess)
        {
            // file upload success
            MessageBox.Show( "文件上传成功!耗时:" + (DateTime.Now - uploadStartTime).TotalSeconds.ToString( "F1" ) + " 秒" );
        }
        else
        {
            // 失败原因多半来自网络异常,还有文件不存在,分类名称填写异常
            // mostly failed by network exception, like offline
            MessageBox.Show( "文件上传失败:" + result.ToMessageShowString( ) );
        }
    }
    else
    {
        MessageBox.Show( "Please Select a File" );
    }
    uploadCacel = null;
}

private async Task<OperateResult> UploadFlieExample( string group )
{
    button_upload.Enabled = false;             // 上传按钮禁用,取消上传按钮使能
    button_upload_cancel.Enabled = true;
    string fileName = textBox3.Text;           // 等待上传的完整文件路径
    System.IO.FileInfo fileInfo = new System.IO.FileInfo( fileName );

    group = string.IsNullOrEmpty( group ) ? textBox_upload_group.Text : group;
    // 开始正式上传,关于三级分类,下面只是举个例子,上传成功后去服务器端寻找文件就能明白
    // start to upload file to server , u shold specify the catgray about the file
    OperateResult result = await mqttSyncClient.UploadFileAsync(
        fileName,                       // 需要上传的原文件的完整路径,上传成功还需要个条件,该文件不能被占用
        group,                          // 类别信息,例如 Files/Personal/Admin
        fileInfo.Name,                  // 在服务器存储的文件名,带后缀,一般设置为原文件的文件名,当然您也可以重新设置名字
        textBox_upload_tag.Text,        // 这个文件的额外描述文本,可以为空("")
        UpdateReportProgress,           // 文件上传时的进度报告,如果你不需要,指定为NULL就行,一般文件比较大,带宽比较小,都需要进度提示
        uploadCacel                     // 用于取消的令牌,不需要取消的话,传NULL即可
        );
    button_upload.Enabled = true;
    button_upload_cancel.Enabled = false;
    return result;
}

// 点击取消上传按钮
private void button_upload_cancel_Click( object sender, EventArgs e )
{
    if (uploadCacel != null) uploadCacel.IsCancelled = true;
}

/// <summary>
/// 用于更新上传进度的方法,该方法是线程安全的
/// </summary>
/// <param name="sended">已经上传的字节数</param>
/// <param name="totle">总字节数</param>
private void UpdateReportProgress( long sended, long totle )
{
    if (progressBar1.InvokeRequired)
    {
        progressBar1.Invoke( new Action<long, long>( UpdateReportProgress ), sended, totle );
        return;
    }


    // 此处代码是安全的
    // thread-safe code
    int value = (int)(sended * 100L / totle);

    label10.Text = SoftBasic.GetSizeDescription( sended ) + "/" + SoftBasic.GetSizeDescription( totle );
    progressBar1.Value = value;
}
删除文件功能
MqttSyncClient mqttSyncClient = new MqttSyncClient( new MqttConnectionOptions( )
{
    ClientId = "ABC",                     // 客户端的唯一的ID信息
    IpAddress = "127.0.0.1",              // 服务器的地址
} );

// 此处演示删除服务器的一个文件,需要这个文件在服务器存在,并且,账户密码,文件操作在服务器验证通过,最终才会删除成功
HslCommunication.OperateResult delete = mqttSyncClient.DeleteFile( "Files/Group/Admin", "D:\\123.txt" );
if (delete.IsSuccess)
{
    // 删除成功
}
else
{
    // 删除失败
    Console.WriteLine( "delete failed, reason:" + delete.Message );
}
遍历指定目录的文件名功能
MqttSyncClient mqttSyncClient = new MqttSyncClient( new MqttConnectionOptions( )
{
    ClientId = "ABC",                     // 客户端的唯一的ID信息
    IpAddress = "127.0.0.1",              // 服务器的地址
} );

// 此处演示遍历目录文件集合
HslCommunication.OperateResult<HslCommunication.Core.GroupFileItem[]> files = mqttSyncClient.DownloadPathFileNames( "Files/Group/Admin" );
if (files.IsSuccess)
{
    foreach (var item in files.Content)
    {
        Console.WriteLine( "文件名:" + item.FileName );
        Console.WriteLine( "下载次数:" + item.DownloadTimes );
        Console.WriteLine( "文件大小:" + item.FileSize );
        Console.WriteLine( "上传人:" + item.Owner );
        Console.WriteLine( "上传时间:" + item.UploadTime );
        Console.WriteLine( "文件描述:" + item.Description );
        Console.WriteLine( );
    }
}
else
{
    // 遍历失败
    Console.WriteLine( "read failed, reason:" + files.Message );
}
遍历指定目录的所有子目录
MqttSyncClient mqttSyncClient = new MqttSyncClient( new MqttConnectionOptions( )
{
    ClientId = "ABC",                     // 客户端的唯一的ID信息
    IpAddress = "127.0.0.1",              // 服务器的地址
} );

// 此处演示遍历目录的子目录
HslCommunication.OperateResult<string[]> files = mqttSyncClient.DownloadPathFolders( "Files" );
if (files.IsSuccess)
{
    foreach (var item in files.Content)
    {
        Console.WriteLine( "目录:" + item );
    }
}
else
{
    // 遍历失败
    Console.WriteLine( "read failed, reason:" + files.Message );
}
上述的两个遍历的方法,就可以遍历出服务器的所有目录和文件了,具体可以参考 Demo 的MQTT文件客户端的演示界面。
参见