sgcMQ 五分钟上手

这个包中附带七个原生消息客户端。MQTT 是最快跑起来的路径,因此本页就以它为例:连接到代理,订阅主题,发布消息,并看着它返回。AMQP、Kafka 和 STOMP 采用相同的双组件结构。

MQTT 3.1.1 和 5.0、AMQP 0.9.1 和 1.0、Kafka、STOMP
无需外部库,也无需 DLL
Standard 版本及以上

两个组件,而不是一个

这是最容易让人犯错的地方。协议组件负责使用 MQTT;另一个单独的客户端组件负责套接字。您只需一次赋值就能把它们连接起来。

协议组件

SGC MQ 组件面板页上的 TsgcWSPClient_MQTT。它提供 Connect、Subscribe、Publish、UnSubscribe 以及十三个 MQTT 事件。

传输组件

基于 WebSocket 的 MQTT 使用 TsgcWebSocketClient,基于 TCP 的普通 MQTT 使用 TsgcTCPClient。请在这个组件上设置 Host 和 Port。

把它们连在一起的那一行

MQTT.Client := WSClient;。之后,您通过设置 WSClient.Active := True 来打开连接,而不是调用协议上的某个方法。

平台

sgcWebSocket_Protocol_MQTT_Client.pas 没有平台保护,只有一个条件性的 Windows 引入,并且该组件使用 ComponentPlatforms(0) 注册。所有目标都能编译。

要求与版本

版本列给出的是控制各个协议的定义,以及它在 Source/sgcVer.inc 中所在的行号。

项目 值
IDE Delphi 7 到 RAD Studio 13,以及 C++Builder 2007 到 13。
uses 子句 TsgcWSPClient_MQTT 使用 sgcWebSocket_Protocols,客户端使用 sgcWebSocket,TsgcWSConnection 使用 sgcWebSocket_Classes,TmqttQoS 使用 sgcWebSocket_Types。
MQTT 版本 SGC_MQTT 定义在第 717 行,位于从第 675 行延伸到第 724 行的 {$IFDEF SGC_EDT_STD} 块内。因此是 Standard 及以上版本。这些块是累加的,所以 Professional、Enterprise 和 All-Access 也包含它。
其他协议 都在同一个 Standard 块中:第 716 行的 SGC_STOMP,第 718 行的 SGC_AMQP,第 719 行的 SGC_AMQP1,第 720 行的 SGC_KAFKA,以及第 715 行的 SGC_WAMP。它们都不是 Enterprise 功能。
版本,独立包 sgcMQ 产品在第 855 行定义 SGC_PACK_MQ,其自己的第 959 行到第 966 行的块会开启相同的五个协议定义。
平台 MQTT 客户端单元上没有单元级平台保护。其 uses 子句中唯一的条件是 {$IFDEF MSWINDOWS}Windows, {$ENDIF}。

想要一个无需自行安装的代理来测试吗?随包附带的 MQTT 演示指向 www.esegece.com 上的公共测试代理,基于 WebSocket 的 MQTT 使用 15675 端口。

安装并找到组件面板页

sgcMQ 包含在 sgcWebSockets 安装程序中,也作为独立的包提供。无论哪种方式,安装流程都相同。

1. 解压

将下载文件解压到一个文件夹,下文称之为 {$DIR}。

2. 库路径

依次选择 Tools、Options、Library。添加 {$DIR}\source 以及与您的 IDE 对应的 lib 文件夹,例如 {$DIR}\libD13\$(Platform)。

3. 构建包

在 {$DIR}\Packages\ 下,打开与您的 IDE 版本对应的包组。先编译运行时 .dpk,再安装设计时 dcl 包。

4. 检查组件面板

会出现一个名为 SGC MQ 的页面,其中包含您的版本所启用的协议客户端。在 Standard 及以上版本的构建中,会有 TsgcWSPClient_MQTT。

5. 打开演示

打开 {$DIR}\Demos\02.WebSocket_Protocols\08.MQTT_Client。下面的代码就来自这里,并且它已经指向一个在线测试代理。

连接、订阅、发布

把协议连接到客户端,打开连接,订阅一个主题并向它发布。消息会通过 OnMQTTPublish 返回。

uClientMQTT.pas
uses
  Classes, SysUtils,
  // sgc
  sgcWebSocket, sgcWebSocket_Classes, sgcWebSocket_Protocols,
  sgcWebSocket_Types, sgcWebSocket_Protocol_MQTT_Client,
  sgcWebSocket_Protocol_MQTT_Message;

procedure TfrmClientPROTOCOL.FormCreate(Sender: TObject);
begin
  WSClient := TsgcWebSocketClient.Create(Self);
  WSClient.Host := 'www.esegece.com';
  WSClient.Port := 15675;
  WSClient.TLS := False;

  // ... attach the client to the MQTT protocol
  MQTT.Client := WSClient;

  // ... and THIS is what opens the connection.
  // There is no Connect call on the protocol component.
  WSClient.Active := True;
end;

如果要使用基于 TCP 的普通 MQTT,而不是基于 WebSocket 的 MQTT,请改为从 sgcTCP_Client_WS 创建一个 TsgcTCPClient,并让 MQTT.Client 指向它。其他一切都不变,这正是这两个组件相互独立的原因。

uClientMQTT.pas
procedure TfrmClientPROTOCOL.btnSubscribeClick(Sender: TObject);
begin
  MQTT.Subscribe('sgc/quickstart');
end;

procedure TfrmClientPROTOCOL.btnPublishClick(Sender: TObject);
begin
  // topic, payload, QoS, retain
  MQTT.Publish('sgc/quickstart', 'hello from Delphi',
    mtqsAtLeastOnce, False);
end;

procedure TfrmClientPROTOCOL.btnUnsubscribeClick(Sender: TObject);
begin
  MQTT.UnSubscribe('sgc/quickstart');
end;

Publish 返回一个 Word,即数据包标识符,并且不会等待。PublishAndWait 返回一个 Boolean,并会阻塞直到代理确认,超时时间默认为十秒。TmqttQoS 来自 sgcWebSocket_Types。

uClientMQTT.pas
procedure TfrmClientPROTOCOL.MQTTMQTTConnect(Connection: TsgcWSConnection;
  const Session: Boolean; const ReasonCode: Integer;
  const ReasonName: String;
  const ConnectProperties: TsgcWSMQTTCONNACKProperties);
begin
  memoLog.Lines.Add('#connected: ' + ReasonName);
end;

procedure TfrmClientPROTOCOL.MQTTMQTTSubscribe(Connection: TsgcWSConnection;
  aPacketIdentifier: Word; aCodes: TsgcWSSUBACKS;
  SubscribeProperties: TsgcWSMQTTSUBACKProperties);
begin
  memoLog.Lines.Add('#subscribed: ' + IntToStr(aPacketIdentifier));
end;

procedure TfrmClientPROTOCOL.MQTTMQTTPublish(Connection: TsgcWSConnection;
  aTopic, aText: string;
  PublishProperties: TsgcWSMQTTPUBLISHProperties);
begin
  memoLog.Lines.Add(aTopic + ': ' + aText);
end;

这是最先需要关注的三个事件。还有另外九个,用于确认流程、断开连接和 MQTT 5.0 身份验证。请让 IDE 生成处理程序,因为参数列表很长,而且每个事件的属性对象各不相同。

这三个选项卡都来自随包附带的演示 Demos\02.WebSocket_Protocols\08.MQTT_Client\uClientMQTT.pas,其中的窗体控件已替换为字面量。在该项目中,MQTT 对象是放置在窗体上的;在代码中创建它的效果完全相同。

验证往返流程

两个事件会告诉您代理已接受您,并且主题已生效。

OnMQTTConnect

代理接受了会话。如果没有被接受,ReasonCode 和 ReasonName 会告诉您原因,这比一个断开的套接字有用得多。

OnMQTTSubscribe

订阅已被批准。aCodes(一个 TsgcWSSUBACKS)携带了代理针对每个主题的回答,因此被拒绝的订阅是可见的,而不是悄无声息。

OnMQTTPublish

收到了一条消息。向您刚订阅的主题发布,它会直接返回,这一次点击就能证明整条路径是通的。

确认事件

在 QoS 1 和 2 下,投递会稍后通过 OnMQTTPubAck、OnMQTTPubRec、OnMQTTPubRel 和 OnMQTTPubComp 确认。如果您需要阻塞式调用,请使用 PublishAndWait。

第一次通常会出什么问题

六个问题几乎涵盖了所有失败的首次连接。

调用 Subscribe 后没有任何反应

连接尚未打开。协议组件不会打开套接字,由客户端来打开。请设置 WSClient.Active := True,并在订阅之前等待 OnMQTTConnect。

第一次调用就出现访问冲突

MQTT.Client 从未被赋值。正是这一行把协议绑定到传输上,没有它,协议就无处可写。

传输方式与端口不匹配

在大多数代理上,基于 WebSocket 的 MQTT 和基于普通 TCP 的 MQTT 使用不同的端口。1883 和 8883 是常用的 TCP 端口,而 WebSocket 端点则完全在别处。随包附带的演示对 WebSocket 使用 15675。

您在寻找 OnMQTTMessage

没有这样的事件。代理发来的入站消息,文本通过 OnMQTTPublish 到达,如果您需要原始负载和完整的消息对象,则通过 OnMQTTPublishEx 到达。

QoS 1 和 2 看起来什么都没做

它们是异步确认的。Publish 会立即返回数据包标识符;确认稍后通过 OnMQTTPubAck、OnMQTTPubRec、OnMQTTPubRel 或 OnMQTTPubComp 到达。如果需要阻塞式调用,请使用 PublishAndWait。

代理拒绝连接

大多数代理需要客户端标识符和凭据。请在 Authentication 上设置它们,如果需要在连接时计算客户端标识符,请使用 OnMQTTBeforeConnect。

第一个主题之后

同样的双组件结构适用于包中的所有其他协议。

MQTT 5.0 属性

设置 MQTTVersion 之后,请求和响应属性对象就可以使用了。用户属性、订阅标识符、主题别名和原因码都会公开。

MQTT 参考

AMQP,两个版本

两个独立的客户端:0.9.1 用于 RabbitMQ 风格的交换器和队列,1.0 用于较新的线路协议。两者与客户端的连接方式都与 MQTT 相同。

AMQP 0.9.1 参考和 AMQP 1.0 参考

Kafka 和 STOMP

一个原生的 Kafka 线路协议客户端,以及 STOMP 1.0 到 1.2,并带有针对 RabbitMQ 和 ActiveMQ 的特定代理变体。

适用于 RabbitMQ 的 STOMP和适用于 ActiveMQ 的 STOMP

连接云端代理

AWS IoT 和 Azure IoT 都使用 MQTT,库附带了专用组件,可为您处理它们的签名和身份验证。

AWS IoT 参考和 Azure IoT 参考

参考、演示和文档

参考页面记录了每个属性和事件。演示项目包含在下载包内,位于 Demos\02.WebSocket_Protocols 下。

参考:MQTT 客户端 TsgcWSPClient_MQTT 上的每个方法、属性和事件。
参考:AMQP 0.9.1 交换器、队列、绑定和消费者。
参考:AMQP 1.0 链路、会话和 1.0 消息模型。
TsgcWSPClient_MQTT 组件页面 MQTT 客户端的完整说明,其余六个协议客户端也可从中链接访问。
协议概览 子协议组件如何附加到客户端或服务器。
在线帮助 自动生成的参考,始终与当前版本保持同步。

相关阅读:发布并等待确认、AMQP 交换器和队列以及 Kafka 客户端。每个产品都有自己的快速入门,列在入门页面上。

sgcMQ 快速入门常见问题

因为协议和传输是两个相互独立的关注点,这使得同一个 MQTT 客户端无需修改您的代码,就能运行在普通 TCP 或 WebSocket 之上。TsgcWSPClient_MQTT 负责编码和解码 MQTT 数据包。TsgcWebSocketClient 或 TsgcTCPClient 负责套接字、主机、端口和 TLS 设置。一次赋值就能把它们连接起来:MQTT.Client := WSClient;。
在客户端组件上,而不是协议上,设置 Active := True。随包附带的演示正是这样做的。协议上也有一个 Connect 方法,但演示没有使用它,设置 Active 是所有示例所遵循的路径。
SGC_MQTT 定义在 sgcVer.inc 的第 717 行,位于从第 675 行延伸到第 724 行的 SGC_EDT_STD 块内。这就是 Standard 版本,即最低的付费层级,而这些块是累加的,因此所有更高的版本也包含它。第 716 行的 STOMP、第 718 行的 AMQP、第 719 行的 AMQP 1.0 和第 720 行的 Kafka 都在同一个块中。所有消息协议都不是 Enterprise 功能。
OnMQTTPublish,其签名是 procedure(Connection: TsgcWSConnection; aTopic, aText: String; PublishProperties: TsgcWSMQTTPUBLISHProperties)。没有名为 OnMQTTMessage 的事件。当您需要原始字节或完整的消息对象,而不是字符串时,请改为处理 OnMQTTPublishEx。
Publish 返回一个 Word,即数据包标识符。送达情况是异步确认的:在 QoS 1 下通过 OnMQTTPubAck,在 QoS 2 下通过 OnMQTTPubRec、OnMQTTPubRel 和 OnMQTTPubComp。如果您想要一个阻塞到代理确认为止的调用,请使用 PublishAndWait,它返回一个 Boolean,并接受一个默认为十秒的超时。
Publish 的第三个参数是 TmqttQoS,声明在 sgcWebSocket_Types.pas 中,成员有 mtqsAtMostOnce、mtqsAtLeastOnce、mtqsExactlyOnce 和 mtqsReserved。默认值是 mtqsAtMostOnce。Subscribe 的第二个参数采用相同的类型。
可以。sgcWebSocket_Protocol_MQTT_Client.pas 没有单元级平台保护,其 uses 子句中唯一的条件是对 Windows 的引入,并且组件面板组件使用 ComponentPlatforms(0) 注册,因此 IDE 不会限制其目标平台。
可以。在协议组件上设置 MQTTVersion。这样 5.0 的属性对象就会生效:发出时使用 ConnectProperties,返回时使用每个事件上的属性参数,例如 OnMQTTConnect 上的 TsgcWSMQTTCONNACKProperties 和 OnMQTTPublish 上的 TsgcWSMQTTPUBLISHProperties。
超值之选:All-AccesseSeGeCe 全部产品,含高级支持,每年 €1,059 起。
查看 All-Access 价格

准备好在您的应用程序背后接入代理了吗?

下载试用版,并针对公共测试代理运行 MQTT 演示。