发布、订阅,以及完整的 QoS 机制
TsgcWSPClient_MQTT 通过一个 MQTTVersion 属性同时覆盖 MQTT 3.1.1 和 MQTT 5.0。QoS 0、1 和 2 均支持,PUBACK、PUBREC、PUBREL 和 PUBCOMP 的交互以事件形式暴露而非被隐藏,另外还有保留消息、Last Will and Testament、通配符订阅和可恢复会话。版本 5 增加了原因码、用户属性、主题别名、共享订阅,以及用于质询响应方案的 AUTH 往返。
七个客户端组件支持 MQTT 3.1.1 和 5.0、AMQP 0.9.1、AMQP 1.0、Apache Kafka 线路协议以及 STOMP 1.0 至 1.2,另有针对 RabbitMQ 和 ActiveMQ 的专用 STOMP 客户端。所有线路格式都在库内部用 Object Pascal 解析和写出,因此不需要外部客户端库、不需要 DLL,也不需要随程序分发任何包装层。sgcMQ 是独立产品,它已内置所基于的 sgcWebSockets Core 运行时,因此无需购买基础授权。
TsgcTCPClient 服务于全部协议
sgcMQ 需要您准备什么,以及字节是如何抵达消息代理的。两个答案都很简短。
它并不依附于某个基础产品。组件所需的一切都已内置在 sgcMQ 中:sgcWebSockets Core 运行时、TCP 载体 TsgcTCPClient、TLS 层以及 JSON 辅助工具。一个 SKU,一个安装程序,无需再购买任何东西。
每份授权都附带完整源代码,因此协议实现可以在您自己的调试器中逐步跟踪,而不是消失在二进制文件里。
包中的每个协议都跑在原始套接字之上,可以明文打开,也可以包裹在 TLS 中。这覆盖了各消息代理的原生端口,也正是 MQTT、AMQP、Kafka 和 STOMP 通常的部署方式,除了包内已有的内容之外不需要任何东西。
如果改为在 WebSocket 之上运行协议,例如 MQTT over WebSocket 或 Web-STOMP,则需要 WebSocket 客户端,而它随 sgcWebSockets 提供,不包含在 sgcMQ 中。请在选择之前先确认您的消息代理对外暴露的是哪种传输。
每个组件都是非可视化组件,您可以把它拖到窗体上,也可以在代码中创建。通过 Client 属性挂上载体,接好协议事件,然后调用该协议自己的动词即可。七个组件的命名风格一致,因此学会一个,其余的也就掌握了大半。
TsgcWSPClient_MQTT 通过一个 MQTTVersion 属性同时覆盖 MQTT 3.1.1 和 MQTT 5.0。QoS 0、1 和 2 均支持,PUBACK、PUBREC、PUBREL 和 PUBCOMP 的交互以事件形式暴露而非被隐藏,另外还有保留消息、Last Will and Testament、通配符订阅和可恢复会话。版本 5 增加了原因码、用户属性、主题别名、共享订阅,以及用于质询响应方案的 AUTH 往返。
TsgcWSPClient_AMQP 使用 AMQP 0.9.1,也就是 RabbitMQ 当初为之设计的协议:信道、交换机和队列声明、绑定、消费者、发布者确认、预取 QoS 以及事务。TsgcWSPClient_AMQP1 使用 AMQP 1.0,即 Azure Service Bus 和 Event Hubs 背后的 OASIS 与 ISO/IEC 19464 标准:容器、会话、发送方和接收方链路、基于信用的流控制、SASL,以及 Claims-Based Security 令牌辅助工具。线路格式不同,对象模型也不同,因此 sgcMQ 为两者各提供一个组件,而不是假装一套 API 能同时适配两者。
TsgcWSPClient_Kafka 在 TCP 之上直接使用 Kafka 线路协议,包括 v2 记录批格式。前面没有 REST 代理,下面也没有 librdkafka。您可以按选定的 acks 级别和 gzip 压缩生产单条记录或批量记录,通过消费者组消费(协调者发现、加入、同步、心跳和再平衡都已代为处理),也可以按偏移量直接读取某个分区。提交偏移量、创建和删除主题、列出消费者组以及探测消息代理能力,全都是一等调用。
TsgcWSPClient_STOMP 处理 STOMP 1.0、1.1 和 1.2:SEND、SUBSCRIBE、UNSUBSCRIBE、ACK、NACK、回执、双向心跳,以及 BEGIN、COMMIT 和 ABORT 事务帧,可接受的版本通过 Versions 声明。两个派生组件把各消息代理的目的地约定变成了具名方法:RabbitMQ 提供 /queue、/topic、/exchange、/amq/queue 和 /temp-queue 辅助方法,ActiveMQ 提供队列和主题辅助方法,外加一个用于该消息代理专有头部的 ActiveMQ_Options 属性。
sgcMQ 实现的是协议规范,而不是包装某家厂商的 SDK,因此任何在线路上使用这些协议的产品都可以作为候选。同一个组件既能对接自建消息代理,也能对接托管云服务,无需改动代码;更换消息代理只涉及一个主机、一个端口和一组凭据。
TsgcWSPClient_AMQP
原生支持 AMQP 0.9.1。STOMP 和 MQTT 插件同样可以访问,各有对应的组件。
TsgcWSPClient_Kafka
在 9092 端口上使用该消息代理自己的二进制协议,也适用于任何兼容 Kafka 线路协议的消息代理。
TsgcWSPClient_MQTT
轻量级 MQTT 消息代理的参考实现,明文使用 1883 端口,TLS 使用 8883 端口。
TsgcWSPClient_MQTT
完整支持 MQTT 5.0,包括共享订阅和用户属性。
TsgcWSPClient_MQTT
支持 MQTT 3.1.1 和 5.0,可自建部署,也可使用厂商云服务。
TsgcWSPClient_STOMP_ActiveMQ
在 61613 端口上使用 STOMP,或用 AMQP 1.0 组件对接 Artemis 的 AMQP 1.0。
TsgcWSPClient_AMQP1
AMQP 1.0 并配备 Claims-Based Security 辅助工具,Event Hubs 也使用同一个组件。
TsgcWSPClient_MQTT
基于 TLS 和客户端证书的 MQTT,通过载体的 TLSOptions 配置。
把一个 TsgcTCPClient 赋给协议组件的 Client 属性,帧就会直接写到套接字上。加密、代理穿透、IPv6 和重连都是该载体上的设置项,因此只需配置一次,无论上层协议是 MQTT、AMQP、Kafka 还是 STOMP,行为都完全一致。
TsgcWSPClient_MQTT
TLS。TsgcWSPClient_AMQP
amqps 监听端口。TsgcWSPClient_AMQP1
TsgcWSPClient_Kafka
TsgcWSPClient_STOMP_RabbitMQ
TsgcWSPClient_STOMP_ActiveMQ
stomp+ssl 连接器。通用的 TsgcWSPClient_STOMP 同样使用 61613 端口,可对接任何支持 STOMP 的消息代理。以上都是惯例默认值,载体的 Port 可以设置为您的部署实际监听的端口。
TLSOptions.IOHandler 可为跨平台构建选择 OpenSSL,或者在您不想分发 OpenSSL 二进制文件时,在 Windows 上选择 SChannel。双向 TLS 可从 PEM 文件、PKCS#12 包或 Windows 证书存储中读取客户端证书。
载体的 WatchDog 会在链路断开后按可配置的间隔和重试次数重新连接,同时每个协议都有自己的存活机制:MQTT 保活 ping、AMQP 心跳、STOMP 心跳,以及 Kafka 消费者组心跳。
HTTP CONNECT 代理支持位于载体上,因此位于企业代理之后的消息代理同样可达,而 IPv6 消息代理地址无需任何额外配置。
读取在独立线程上运行,入站帧以带类型的事件送达:OnMQTTPublish、OnAMQPBasicDeliver、OnKafkaMessage、OnSTOMPMessage。设置载体的通知选项,即可为 VCL 和 FMX 代码把它们编排到主线程上。
把一个 TsgcTCPClient 与协议组件配对,设置凭据,接好事件,然后调用协议动词。Object Pascal 和 C++ Builder 中的写法一致,其余六个组件的写法也一致。
uses
sgcTCP_Client_WS, sgcWebSocket_Classes, sgcWebSocket_Types,
sgcWebSocket_Protocols, sgcWebSocket_Protocol_MQTT_Client,
sgcWebSocket_Protocol_MQTT_Message;
var
TCPClient: TsgcTCPClient;
MQTT: TsgcWSPClient_MQTT;
begin
TCPClient := TsgcTCPClient.Create(nil); // plain MQTT over TCP
TCPClient.Host := 'broker.example.com';
TCPClient.Port := 1883;
TCPClient.WatchDog.Enabled := True;
MQTT := TsgcWSPClient_MQTT.Create(nil);
MQTT.Client := TCPClient;
MQTT.MQTTVersion := mqtt5;
MQTT.Authentication.Enabled := True;
MQTT.Authentication.UserName := 'sgc';
MQTT.Authentication.Password := 'sgc';
MQTT.LastWillTestament.Enabled := True;
MQTT.LastWillTestament.Topic := 'devices/sensor-01/status';
MQTT.LastWillTestament.Message := 'offline';
MQTT.LastWillTestament.QoS := mtqsAtLeastOnce;
MQTT.LastWillTestament.Retain := True;
MQTT.OnMQTTConnect := MQTTConnect;
MQTT.OnMQTTPublish := MQTTPublish;
TCPClient.Active := True;
end;
procedure TForm1.MQTTConnect(Connection: TsgcWSConnection;
const Session: Boolean; const ReasonCode: Integer;
const ReasonName: string;
const ConnectProperties: TsgcWSMQTTCONNACKProperties);
begin
MQTT.Subscribe('sensors/+/temperature', mtqsAtLeastOnce);
MQTT.Publish('devices/sensor-01/status',
'online', mtqsAtLeastOnce, True); // retained
end;
procedure TForm1.MQTTPublish(Connection: TsgcWSConnection;
aTopic, aText: string;
PublishProperties: TsgcWSMQTTPublishProperties);
begin
Memo1.Lines.Add(aTopic + ' = ' + aText);
end;
// For an encrypted broker: same code, TLS on the carrier.
TCPClient.Port := 8883;
TCPClient.TLS := True;
// include: sgcTCP_Client_WS.hpp, sgcWebSocket_Protocols.hpp,
// sgcWebSocket_Protocol_MQTT_Client.hpp,
// sgcWebSocket_Protocol_MQTT_Message.hpp
TsgcTCPClient *TCPClient = new TsgcTCPClient(this); // plain MQTT over TCP
TCPClient->Host = "broker.example.com";
TCPClient->Port = 1883;
TCPClient->WatchDog->Enabled = true;
TsgcWSPClient_MQTT *MQTT = new TsgcWSPClient_MQTT(this);
MQTT->Client = TCPClient;
MQTT->MQTTVersion = mqtt5;
MQTT->Authentication->Enabled = true;
MQTT->Authentication->UserName = "sgc";
MQTT->Authentication->Password = "sgc";
MQTT->LastWillTestament->Enabled = true;
MQTT->LastWillTestament->Topic = "devices/sensor-01/status";
MQTT->LastWillTestament->Message = "offline";
MQTT->LastWillTestament->QoS = mtqsAtLeastOnce;
MQTT->LastWillTestament->Retain = true;
MQTT->OnMQTTConnect = MQTTConnect;
MQTT->OnMQTTPublish = MQTTPublish;
TCPClient->Active = true;
void __fastcall TForm1::MQTTPublish(TsgcWSConnection *Connection,
UnicodeString aTopic, UnicodeString aText,
TsgcWSMQTTPublishProperties PublishProperties)
{
Memo1->Lines->Add(aTopic + " = " + aText);
}
MQTT->Subscribe("sensors/+/temperature", mtqsAtLeastOnce);
MQTT->Publish("sensors/room1/temperature",
"{\"value\":22.5,\"unit\":\"C\"}", mtqsAtLeastOnce, true);
// For an encrypted broker: same code, TLS on the carrier.
TCPClient->Port = 8883;
TCPClient->TLS = true;
这套消息包没有任何平台限制。全部七个客户端以及它们之下的载体,都为编译器所能生成的每一个目标平台注册,从 Windows 服务到 Android 手机,全部出自同一份源代码树。
TsgcTCPClient 载体
套接字、TLS、代理、IPv6 以及 WatchDog 重连
TLSOptions.IOHandler 选择
sgcMQ 单独授权,单个开发者起价 €249。所有授权均包含完整源代码、1 年更新,以及 50% 到 70% 的续订折扣:续订 1 个包为 50%,2 个包为 60%,3 个及以上为 70%。sgcAI 和 sgcMQ 各算作一个包。
€249
提供 Single、Team 和 Site 授权。
sgcMQ 已包含 sgcWebSockets Core 运行时,因此无需再购买任何东西。
结算页面会列出两项:sgcWebSockets Core 运行时授权(计价为零)以及 sgcMQ 包本身。查看完整价格详情。
把 sgcMQ 与我们其他的 Delphi、C++ Builder 和 .NET 组件库搭配使用。