sgcIndy 五分钟上手
sgcIndy 是 Indy 的维护版构建,而不是换了名字的分支。单元名称、类名称和组件面板页都与您已经在用的一样,因此这份快速入门不是“编写这段代码”,而是“安装它,重新构建,然后设置一个新属性”。
sgcIndy 是 Indy 的维护版构建,而不是换了名字的分支。单元名称、类名称和组件面板页都与您已经在用的一样,因此这份快速入门不是“编写这段代码”,而是“安装它,重新构建,然后设置一个新属性”。
没有 sgcId 前缀。没有一个单元,没有一个类。您现有的代码无需改动即可编译。
普通的 Indy 名称。IdTCPClient、IdHTTP、IdSSLOpenSSL,以及大约四百个其他单元。库中没有任何单元以 sgc 前缀命名。
同样是普通的 Indy 名称:TIdTCPClient、TIdHTTP、TIdSSLIOHandlerSocketOpenSSL、TIdSSHClient、TIdSFTPClient。
还是那五个:Indy Clients、Indy Servers、Indy Intercepts、Indy I/O Handlers 和 Indy Misc。其中大约有 166 个组件,就在您一直查看的位置。
安装程序会切换 IDE 加载的包,并重写搜索路径。您的项目不需要改变。可见的区别是一个新属性 SSLOptions.APIVersion,以及底层的各项修复。
sgcIndy 没有功能层级。许可证层级改变的是包里有什么,而不是代码能做什么。
| 项目 | 值 |
|---|---|
| IDE | Delphi 7 到 RAD Studio 13,以及 C++Builder 2007 到 13。每个版本都附带包组。 |
| uses 子句 | 保持不变。您的项目中原有的写法都能继续工作,因为单元名称与标准 Indy 完全相同。 |
| Indy 基础版本 | 该库自报为 Indy 10.6.3.12。sgc 的改动在原始单元内部用注释和条件定义标出,而不是通过重命名。 |
| 版本 | 没有功能层级。版本标志在构建时注入,只有两个使用者:关于对话框和 IDE 启动画面。库中没有任何内容受它限制。层级真正改变的是打包方式:Community 和 Basic 构建附带已编译的二进制文件,不包含 .pas 和 .inc 文件,而源代码构建则包含它们。 |
| FreePascal 和 Lazarus | 支持。附带一个 Lazarus 包,以及 FreePascal 包存根和构建文件,编译器梯度覆盖 FPC 2.2.2 到 3.3.1。有一点需要注意:Delphi 模式在 Lazarus 中被有意禁用,因此假定使用该模式的单元需要调整。 |
| 平台 | Windows、Linux、macOS、FreeBSD、iOS 和 Android 都有各自的条件块。在 iOS 上,OpenSSL 必须静态链接。 |
开始之前最有用的一点:由于单元名称与 RAD Studio 自带的 Indy 冲突,安装程序会替您完成切换。它会注销内置的 Indy 设计时包,注册自己的包,并重写 IDE 的搜索路径。
安装程序会完成这些工作。重要的是在之后确认 IDE 确实加载了 sgcIndy。
运行下载的安装程序,勾选您需要的 RAD Studio 版本和平台。它会复制库,对于 Community 和 Basic 包,则不包含源文件。
安装程序会注销 IDE 内置的 Indy 设计时包,并在原位置注册自己的包。这使得相同的单元名称解析到 sgcIndy。
它会把 sgcIndy 文件夹放到每个平台的 IDE 搜索路径最前面,并移除之前安装留下的过时条目。
重启 IDE。启动画面会显示 sgcIndy,Indy 关于对话框也会这样显示。这就是确认切换已生效的检查方法。
打开您现有的 Indy 项目并重新构建。不要改动 uses 子句。如果它能针对标准 Indy 编译,就能针对它编译。
第一个选项卡是您现有项目本来的样子。第二个是值得添加的一行新代码。第三个证明您使用的是 sgcIndy,而不是标准 Indy。
// This is a shipped sgcIndy demo's uses clause.
// Read it twice: there is not one sgc prefix in it.
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient,
IdHTTP, IdIOHandler, IdIOHandlerSocket, IdIOHandlerStack, IdSSL,
IdSSLOpenSSL, IdSSLOpenSSLHeaders, StdCtrls;
您现有的项目已经是这个样子,这正是重点。没有 sgcIdTCPClient,也没有 TsgcIdSSLIOHandlerSocketOpenSSL,因为库中没有任何单元和类带有 sgc 前缀。安装,重新构建,完成。
procedure TFRMHttpClient.btnGoToClick(Sender: TObject);
var
oStream: TStringStream;
begin
// Two separate settings. APIVersion picks which generation of the
// OpenSSL API to call, Method picks the TLS version. TLS 1.3 needs
// the 3.0 API, so both lines change together.
IdSSLIOHandlerSocketOpenSSL1.SSLOptions.APIVersion := sslvAPI_3_0;
IdSSLIOHandlerSocketOpenSSL1.SSLOptions.Method := sslvTLSv1_3;
oStream := TStringStream.Create('');
try
IdHTTP1.Get(txtURL.Text, oStream);
finally
FreeAndNil(oStream);
end;
end;
TIdSSLAPIVersion 的成员有 sslvAPIDefault、sslvAPI_1_0、sslvAPI_1_1 和 sslvAPI_3_0。该类型和该属性在标准 Indy 中都不存在,因此这段代码可以在编译时证明您构建所针对的是哪个库。
procedure TfrmTCPClient.btnConnectClick(Sender: TObject);
begin
IdSSLIOHandlerSocketOpenSSL1.SSLOptions.APIVersion := sslvAPI_3_0;
IdSSLIOHandlerSocketOpenSSL1.SSLOptions.Method := sslvTLSv1_3;
IdTCPClient1.Host := txtHost.Text;
IdTCPClient1.Port := StrToInt(txtPort.Text);
IdSSLIOHandlerSocketOpenSSL1.PassThrough := False;
IdTCPClient1.Connect;
end;
procedure TfrmTCPClient.btnDisconnectClick(Sender: TObject);
begin
IdTCPClient1.Disconnect;
end;
组件相同,属性相同,组件面板页也相同。PassThrough := False 会把普通套接字变成 TLS 套接字,与标准 Indy 中完全一样。读取使用 IdTCPClient1.IOHandler.ReadLn,写入使用 IOHandler.Write,都没有变化。
前两个选项卡来自随包附带的演示 Demos\HttpClient\FHttpClient.pas,其中的组合框已替换为字面量。共附带十八个演示,包括 SSH 和 SFTP 客户端、FTP 客户端、邮件客户端、TCP 服务器以及一对 UDP 演示。
由于单元名称完全相同,您无法从自己的源代码判断。这里有三项明确无误的检查。
安装后重启 IDE。启动画面会显示 sgcIndy。这是确认包切换已生效的检查方法,也是最快的一种。
Indy 关于对话框显示的是 eSeGeCe,而不是标准文本,并且在免费包上会显示 Community Edition。
SSLOptions.APIVersion := sslvAPI_3_0;。标准 Indy 中不存在 TIdSSLAPIVersion 类型,因此如果这一行能够构建,就说明您使用的是 sgcIndy。
不改动 uses 子句,直接重新构建。它应该与之前完全一样地编译,因为单元名称和类名称完全相同。
六个问题几乎涵盖了所有迁移的情况。
没有这样的单元。库中零个单元、零个类带有 sgc 前缀。如果您把 uses 子句改写为 sgcIdTCPClient,项目将无法编译,因为不存在这样的单元。
包的切换由安装程序处理,因此这通常意味着安装没有完成,或者某个手动添加的搜索路径条目优先生效。请检查启动画面,切换生效时它会显示 sgcIndy。
请同时设置两个属性。SSLOptions.APIVersion 选择使用哪一代 OpenSSL API,SSLOptions.Method 选择协议版本。TLS 1.3 需要 3.0 API,因此两行必须一起更改。
每个演示文件夹都在可执行文件旁边附带它所需的那一组文件。对于 3.0 API,是 libcrypto-3.dll 和 libssl-3.dll。较旧的 API 使用的名称不同,复制了错误的一对,是握手尚未开始就失败的常见原因。
在编译器定义中,Delphi 模式在 Lazarus 构建中被有意关闭,并附有一条注释说明它在那里会失败。依赖 Delphi 模式语义的代码需要调整。
Community 和 Basic 安装程序附带已编译的二进制文件,不包含 .pas 和 .inc 文件。如果您需要单步调试进入库内部,就需要包含源代码的包。
重新构建完成之后,值得了解的四件事。
标准 Indy 10.6.2 早于 OpenSSL 1.1 和 3.0 的 API 变更。SSLOptions.APIVersion 选择使用哪一代 API,在 3.0 API 上就可以使用 sslvTLSv1_3。
IdTCPClient、IdHTTP、IdSSLOpenSSL 等等,每个类也保留其原始名称,TIdTCPClient、TIdHTTP、TIdSSLIOHandlerSocketOpenSSL。库中任何地方都没有带 sgc 前缀的单元或类。安装它,重新构建,您的项目就运行在 sgcIndy 上了。
SSLOptions.APIVersion 只存在于此构建中,因此给它赋值 sslvAPI_3_0 的那一行在这里可以编译,而针对标准 Indy 则会失败。
SSLOptions.APIVersion := sslvAPI_3_0 选择 OpenSSL 3.0 API,SSLOptions.Method := sslvTLSv1_3 选择协议。TIdSSLAPIVersion 类型的成员有 sslvAPIDefault、sslvAPI_1_0、sslvAPI_1_1 和 sslvAPI_3_0,TIdSSLVersion 新增了 sslvTLSv1_3。然后像演示那样,把 libcrypto-3.dll 和 libssl-3.dll 放在可执行文件旁边。
.pas 和 .inc 文件,而带源代码的包则包含它们。