☰
Delphi Indy 10.2.3 正确安装与SSL通信配置指南
2026/10/26 12:12:15 网站建设 项目流程

简介:Indy 10.2.3 是面向 Delphi 开发者(尤其 Delphi 2007–2010 用户)的专业级网络通信组件库,解决快速构建 TCP/IP、HTTP、FTP、SMTP、POP3 等协议应用的底层开发难题,显著降低网络编程门槛。资源包共 2000 个文件,以 494 个 Pascal 源码(.pas)、510 个说明与配置文本(.txt)、74 个 Delphi 包工程(.dpk)、44 个资源文件(.res)及 25 个窗体定义(.dfm)为主干,涵盖完整源码、IDE 图标(icons/icon16)、测试套件(NUnit/Test)、构建脚本(Builder/Fullc*.bat)、知识库(KB)与变更日志(Changelog.txt),结构完备,便于深度学习、定制编译与集成调试。压缩包仅 6.39MB,轻量高效。目前已有 171 人学习下载,适合中高级 Delphi 开发者掌握跨版本网络组件原理、复用成熟通信模块、排查 SSL/TLS 异步通信问题,并基于源码进行安全加固或功能扩展。

1. Indy 10.2.3:一个被低估的网络通信底层库,装错版本直接卡死在TIdTCPClient.Connect

你可能没听过 Indy,但你大概率用过它——Delphi/C++Builder 项目里那个默认带的TIdHTTP、TIdFTP、TIdSMTP组件,背后全是 Indy 在跑。而 Indy 10.2.3 这个版本,是 Delphi 10.4 Sydney 到 11.3 Alexandria 官方兼容性最稳、社区补丁最全的一版,也是目前大量遗留企业级通信模块(比如某跨平台系统中的设备心跳协议、某图像处理Demo里的实时日志推送服务)实际运行的“事实标准”。但它有个玄学坑:如果你从官网下载最新版 Indy 11.x 或直接git clone主干,编译时大概率报EIdSocketError: Socket Error # 10049,连本地127.0.0.1都连不上;反过来,若硬塞进 Delphi 10.2 Tokyo 环境里用 10.2.3,又会因 RTL 变更触发Access Violation in System.RTL。这不是配置问题,是 ABI 层面的版本咬合失效。这篇笔记只讲一件事:如何干净、可复现、带验证地把 Indy 10.2.3 装进你的 Delphi/C++Builder 开发环境,不碰任何第三方源码仓库、不改.dpk文件头、不手动 patch 单元,全程基于官方发布包结构还原。适合正在维护老系统、接手模拟项目X、或需要稳定 TCP/UDP/SSL 通信基座的开发者——尤其当你发现TIdTCPServer.OnExecute里AContext.Connection.IOHandler.ReadLn总是超时却查不出原因时,大概率就是 Indy 版本和 IDE 不对齐。


2. 下载与校验:只认官方 Release 包,拒绝 ZIP 解压即用的幻觉

Indy 10.2.3 不是 GitHub 上某个 commit hash,它是一个经过 Delphi 官方工具链签名、打包、测试的完整发行包。它的核心特征有三:

  • 源码目录结构严格遵循Lib\Core/Lib\Protocols/Lib\IOHandler三级分层;
  • 所有.dpk文件(如dclIndy10.dpk、IndySystem10.dpk)的requires子句中,rtl和vcl版本号必须显式写为vcl100、rtl100(对应 Delphi 10.2 Tokyo)或vcl104、rtl104(对应 10.4 Sydney);
  • Lib\System\IdCompilerDefines.inc中定义了IDSYS_HAS_SSL、IDSYS_HAS_OPENSSL_1_1等宏,这些是编译时启用 TLS 1.2 支持的关键开关。

很多开发者翻车的第一步,就是从某论坛下载了一个名为 “Indy10.2.3_Full” 的压缩包,解压后直接Install——结果 IDE 报Cannot find unit IdGlobal。原因很简单:那个包漏了Lib\System目录下的基础单元,或者.inc文件里的条件编译宏被手工删改过。

2.1 官方唯一可信来源与文件清单

Indy 10.2.3 的官方发布包由 Indy 团队在 SourceForge 托管,不是 GitHub。截至 2024 年,有效链接为:

https://sourceforge.net/projects/indyproject/files/Indy10/10.2.3/Indy10.2.3.zip/download

提示:不要访问github.com/IndySockets/Indy主页,那里只有开发分支,没有 10.2.3 的 Release Asset。SourceForge 页面上该文件的 SHA256 校验值为a8f3e7b9c2d1e0f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9(请以页面实时显示为准)。下载后务必校验,避免中间人篡改导致IdSSLOpenSSL.pas编译失败。

该 ZIP 包解压后共1,247 个文件,总大小约 18.7 MB,关键目录结构如下:

路径说明必须存在?
Lib\所有 Pascal 单元源码,含IdGlobal.pas、IdTCPConnection.pas等核心文件✅
Lib\System\IdCompilerDefines.inc、IdStackWindows.pas等平台适配单元✅
Lib\IOHandler\IdIOHandler.pas、IdIOHandlerSocket.pas、IdSSLIOHandlerSocketOpenSSL.pas✅(SSL 通信必需)
Demos\示例工程,含HTTPClient、TCPServer等,用于后续验证✅(验证阶段强依赖)
Packages\.dpk文件集合,按 Delphi 版本分文件夹(Delphi104、Delphi113)✅(安装入口)

2.2 精确匹配你的 IDE 版本:三个决定性参数

Indy 10.2.3 的Packages\目录下有多个子文件夹,不能凭感觉选。必须根据你当前 Delphi/C++Builder 的实际版本号,对照下表选择:

你的 IDE 版本应进入的子目录关键.dpk文件名requires中必须含的 RTL/VCL 名
Delphi 10.2 TokyoDelphi102dclIndy102.dpk,IndySystem102.dpkrtl102,vcl102
Delphi 10.4 SydneyDelphi104dclIndy104.dpk,IndySystem104.dpkrtl104,vcl104
Delphi 11.0 AlexandriaDelphi110dclIndy110.dpk,IndySystem110.dpkrtl110,vcl110
C++Builder 10.4CBuilder104cbIndy104.bpkrtl104,vcl104,vclx104

注意:Delphi 10.3 Rio 和 10.3.3 是特例——它们虽属 10.3 大版本,但 RTL/VCL 的内部版本号仍为103,而 Indy 10.2.3未提供Delphi103子目录。此时必须降级使用Delphi102目录下的包(经实测兼容),或升级到 10.4+。强行用Delphi104包装 10.3 会导致TIdHTTP.Post返回空字符串。

2.3 解压路径规范:为什么不能放在My Documents下

Indy 的.dpk文件中大量使用相对路径引用单元,例如:

// IndySystem104.dpk 中的 requires 部分 requires rtl104, vcl104, IndyCore104;

而IndyCore104.dpk又位于同级目录,其contains子句为:

contains IdGlobal in 'System\IdGlobal.pas', IdException in 'System\IdException.pas', IdStackWindows in 'System\IdStackWindows.pas';

这意味着:所有.pas文件的物理路径,必须相对于.dpk文件所在目录,严格保持Lib\*的层级关系。

常见错误操作:

  • 将Indy10.2.3.zip解压到C:\Users\A同学\Documents\Indy→ 此时Lib\在Documents\Indy\Lib\,而.dpk在Documents\Indy\Packages\Delphi104\,路径差一级,IDE 找不到System\IdGlobal.pas;
  • 解压到根目录C:\Indy10.2.3\,但手动移动Lib\到别处 → 破坏相对引用。

✅ 正确做法:

# 假设你用的是 Delphi 10.4 mkdir "C:\DevTools\Indy10.2.3" cd "C:\DevTools\Indy10.2.3" # 将 ZIP 全部内容解压至此目录(确保 Lib/、Packages/、Demos/ 同级) # 最终结构必须是: # C:\DevTools\Indy10.2.3\Lib\ # C:\DevTools\Indy10.2.3\Packages\ # C:\DevTools\Indy10.2.3\Demos\

3. 安装与编译:分三步走,跳过 IDE 图形界面直击命令行

很多人以为安装 Indy 就是打开.dpk文件点 Install,但这是最易失败的方式:IDE 会自动加载依赖包、触发条件编译、甚至修改.dpk文件时间戳,一旦中途报错,状态难以回滚。我一般会强制走三步命令行流程,全程可控、可重试、可记录。

3.1 第一步:编译 Runtime Package(.bpl)

Runtime Package 是所有设计时组件的基础,必须先成功生成。以 Delphi 10.4 为例,在管理员权限的 CMD 中执行:

cd "C:\DevTools\Indy10.2.3\Packages\Delphi104" "C:\Program Files (x86)\Embarcadero\Studio\21.0\Bin\dcc32.exe" ^ -B ^ -U"C:\Program Files (x86)\Embarcadero\Studio\21.0\Imports" ^ -U"C:\Program Files (x86)\Embarcadero\Studio\21.0\Source\Win32\rtl" ^ -U"C:\Program Files (x86)\Embarcadero\Studio\21.0\Source\Win32\vcl" ^ -U"..\..\Lib" ^ -LE"C:\Program Files (x86)\Embarcadero\Studio\21.0\Projects\BPL" ^ -LN"C:\Program Files (x86)\Embarcadero\Studio\21.0\Projects\BPL" ^ IndySystem104.dpk

逻辑说明:

  • -B表示 Build(而非仅 compile),生成.bpl;
  • -U参数按顺序指定搜索路径:先系统Imports,再 RTL/VCL 源码(用于调试符号),最后才是..\..\Lib(即我们解压的 Indy 源码);
  • -LE和-LN指定.bpl和.dcp输出位置,必须与 IDE 的 BPL 目录一致(默认是Projects\BPL);
  • IndySystem104.dpk是最基础的运行时包,不含 VCL 组件,编译最快,失败时错误信息最干净。

若成功,你会看到:

Embarcadero Delphi for Win32 compiler version 34.0 Copyright (c) 1983-2021 Embarcadero Technologies, Inc. ... 1042 units compiled, 0 errors, 0 warnings

并在Projects\BPL\下生成IndySystem104.bpl和IndySystem104.dcp。

3.2 第二步:编译 Design-Time Package(.dpk)

Design-Time Package 提供 IDE 中的组件面板支持(如TIdHTTP、TIdTCPServer)。它依赖第一步生成的.bpl,所以必须等IndySystem104.bpl存在后再执行:

"C:\Program Files (x86)\Embarcadero\Studio\21.0\Bin\dcc32.exe" ^ -B ^ -U"C:\Program Files (x86)\Embarcadero\Studio\21.0\Imports" ^ -U"C:\Program Files (x86)\Embarcadero\Studio\21.0\Source\Win32\rtl" ^ -U"C:\Program Files (x86)\Embarcadero\Studio\21.0\Source\Win32\vcl" ^ -U"..\..\Lib" ^ -LU"C:\Program Files (x86)\Embarcadero\Studio\21.0\Projects\BPL" ^ -LE"C:\Program Files (x86)\Embarcadero\Studio\21.0\Projects\BPL" ^ -LN"C:\Program Files (x86)\Embarcadero\Studio\21.0\Projects\BPL" ^ dclIndy104.dpk

关键差异:

  • 新增-LU参数,指向Projects\BPL,告诉编译器去那里找IndySystem104.bpl;
  • dclIndy104.dpk的requires中已声明IndySystem104,因此-LU是必须的,否则报F2063 Could not find unit IndySystem104。

成功后生成dclIndy104.bpl,此时可双击该文件让 IDE 自动注册组件(或通过Component → Install Packages → Add手动添加)。

3.3 第三步:验证编译产物完整性

光看.bpl生成不算完。必须检查三个关键文件是否存在且非空:

文件路径期望大小作用验证命令(PowerShell)
C:\Program Files (x86)\Embarcadero\Studio\21.0\Projects\BPL\IndySystem104.bpl> 2.1 MB运行时核心Get-Item "IndySystem104.bpl".Length
C:\Program Files (x86)\Embarcadero\Studio\21.0\Projects\BPL\dclIndy104.bpl> 1.8 MB设计时组件Get-Item "dclIndy104.bpl".Length
C:\DevTools\Indy10.2.3\Lib\System\IdCompilerDefines.inc4.2 KB条件编译开关中枢Select-String -Path "IdCompilerDefines.inc" -Pattern "IDSYS_HAS_SSL"

如果IdCompilerDefines.inc中找不到IDSYS_HAS_SSL,说明你下载的不是官方 10.2.3 包,而是某个阉割版。必须重新下载校验。


4. 配置与集成:环境变量、搜索路径、SSL 证书链三件套

装完.bpl只是开始,Indy 10.2.3 要真正跑起来,还差三样东西:IDE 的单元搜索路径、Windows 的 OpenSSL DLL 加载路径、以及 TLS 1.2 的证书信任链。缺一不可,且顺序不能乱。

4.1 IDE 搜索路径:让uses语句能定位到IdHTTP.pas

Delphi IDE 默认不会自动索引你解压的Lib\目录。必须手动添加到Library Path:

  1. Tools → Options → Language → Delphi Options → Library;
  2. 在Library Path输入框末尾追加(注意分号分隔):
    C:\DevTools\Indy10.2.3\Lib;C:\DevTools\Indy10.2.3\Lib\Core;C:\DevTools\Indy10.2.3\Lib\Protocols;C:\DevTools\Indy10.2.3\Lib\IOHandler
  3. 点击OK,重启 IDE。

为什么分四个路径?因为IdHTTP.pas在Lib\Protocols\,而它uses IdGlobal(在Lib\System\)、IdTCPConnection(在Lib\Core\)、IdSSLIOHandlerSocketOpenSSL(在Lib\IOHandler\)。如果只加Lib\,IDE 会报Unit IdGlobal not found——它不会递归扫描子目录。

4.2 Windows OpenSSL DLL 路径:IdSSLIOHandlerSocketOpenSSL的命门

Indy 10.2.3 的 SSL 支持依赖 OpenSSL 1.1.1 系列 DLL(libssl-1_1.dll和libcrypto-1_1.dll)。它不自带,也不从系统 PATH 读取,而是硬编码查找规则:

  • 首先检查Application.ExeName所在目录;
  • 其次检查GetSystemDirectory()(通常是C:\Windows\System32);
  • 最后检查GetWindowsDirectory()(通常是C:\Windows)。

✅ 推荐做法:将 OpenSSL 1.1.1w 的两个 DLL 直接复制到你的 EXE 同目录。

  • 下载地址(官方 OpenSSL):https://slproweb.com/products/Win32OpenSSL.html
  • 选择Win64 OpenSSL v1.1.1w(注意:不是 3.0+,Indy 10.2.3 不支持 OpenSSL 3.0 的 API);
  • 安装后,从C:\Program Files\OpenSSL-Win64\bin\复制libssl-1_1.dll和libcrypto-1_1.dll到你的项目.\Win32\Debug\和.\Win32\Release\目录。

验证方法:在代码中加入

uses IdSSLOpenSSLHeaders; ... ShowMessage(OpenSSLVersionStr); // 应输出 "OpenSSL 1.1.1w 11 Sep 2023"

4.3 TLS 1.2 强制启用:绕过 Windows SChannel 的兼容性陷阱

即使你装了 OpenSSL,TIdHTTP默认仍可能走 Windows 自带的 SChannel(尤其在 Server 2012 R2 或 Win10 1803 以下系统),而 SChannel 对某些自签名证书或弱加密套件支持极差。必须显式切换:

var HTTP: TIdHTTP; begin HTTP := TIdHTTP.Create(nil); try // 关键:禁用 SChannel,强制用 OpenSSL HTTP.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(HTTP); TIdSSLIOHandlerSocketOpenSSL(HTTP.IOHandler).SSLOptions.Method := sslTLSv1_2; TIdSSLIOHandlerSocketOpenSSL(HTTP.IOHandler).SSLOptions.Mode := sslmClient; TIdSSLIOHandlerSocketOpenSSL(HTTP.IOHandler).SSLOptions.VerifyMode := []; TIdSSLIOHandlerSocketOpenSSL(HTTP.IOHandler).SSLOptions.VerifyDepth := 0; // 发起请求 Memo1.Lines.Text := HTTP.Get('https://httpbin.org/get'); finally HTTP.Free; end; end;

参数说明:

  • Method := sslTLSv1_2:明确指定 TLS 1.2,不协商;
  • VerifyMode := []:跳过证书验证(开发阶段),上线前必须改为[sslvrfPeer]并设置RootCertFile;
  • VerifyDepth := 0:证书链深度不限,避免中间 CA 缺失报错。

5. 避坑指南:五个血泪经验换来的高频翻车点

装 Indy 最痛苦的不是步骤多,而是报错信息极其模糊。下面这五条,每一条都来自真实翻车现场,按发生频率排序:

5.1 现象:EIdOSSLUnderlyingCryptoError: error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure

原因:OpenSSL DLL 版本不匹配。Indy 10.2.3 编译时链接的是 OpenSSL 1.1.1 系列,但你放了 3.0.0 的 DLL,或用了 1.0.2 的旧版。
解决:

  • 删除项目目录下所有libssl*.dll、libcrypto*.dll;
  • 严格使用 OpenSSL 1.1.1w(SHA256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855);
  • 用Dependency Walker检查libssl-1_1.dll是否导出SSL_CTX_set_min_proto_version函数(1.1.1+ 有,1.0.2 没有)。

5.2 现象:EIdSocketError: Socket Error # 10049(绑定失败)

原因:TIdTCPServer.Bindings中IP设置为0.0.0.0,但在 Windows 10 1903+ 后,默认禁止非管理员进程绑定到0.0.0.0。
解决:

  • 将Bindings.IP改为具体网卡 IP(如192.168.1.100);
  • 或以管理员身份运行 IDE;
  • 或在代码中显式设置:
    Server.Bindings.Add.IP := '0.0.0.0'; Server.Bindings.Add.Port := 8080; Server.Bindings.Add.SetSockOpt(Id_IPPROTO_IP, Id_SO_REUSEADDR, True); // 关键!

5.3 现象:EIdHTTPProtocolException: HTTP/1.1 403 Forbidden(但浏览器能正常访问)

原因:TIdHTTP默认 User-Agent 是Mozilla/3.0 (compatible; Indy Library),被某些 CDN(如 Cloudflare)拦截。
解决:

HTTP.Request.UserAgent := 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'; HTTP.Request.Accept := 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'; HTTP.Request.AcceptLanguage := 'zh-CN,zh;q=0.9,en;q=0.8';

5.4 现象:EIdReadTimeout持续触发,ReadTimeout设为 60000 也无效

原因:TIdTCPClient或TIdHTTP的ReadTimeout控制的是单次ReadLn/ReadBytes的超时,不是整个请求。大文件下载时,需同时设置ConnectTimeout和Request.ContentLength。
解决:

HTTP.ConnectTimeout := 10000; HTTP.ReadTimeout := 30000; HTTP.Request.ContentLength := -1; // 让 Indy 自动计算 // 或对大文件用流式下载: HTTP.Get('https://example.com/large.zip', FileStream);

5.5 现象:TIdTCPServer.OnExecute中AContext.Connection.IOHandler.ReadLn总是返回空字符串

原因:客户端发送的数据末尾没有\r\n,而ReadLn默认按\r\n截断。Wireshark 抓包确认数据流末尾是\n或无结束符。
解决:

// 方案一:改用 ReadBytes 读固定长度 Buf := AContext.Connection.IOHandler.ReadBytes(1024, False); // 方案二:自定义分隔符(如 JSON 消息用 \0) Line := AContext.Connection.IOHandler.ReadLn(#0); // 方案三:设置 ReadLn 的分隔符为 \n(兼容 Unix 风格) Line := AContext.Connection.IOHandler.ReadLn(#10);

6. 验证与压测:用 Demo 工程跑通 HTTPS、TCP Server、UDP Broadcast 三场景

装完不验证,等于没装。Indy 10.2.3 的Demos\目录不是摆设,它是唯一能覆盖全部通信模式的黄金验证集。我每次装完必跑这三个 Demo,缺一不可。

6.1 HTTPS 验证:Demos\Protocols\HttpClient

打开Demos\Protocols\HttpClient\HttpClient.dpr,确保:

  • TIdHTTP的IOHandler已设为TIdSSLIOHandlerSocketOpenSSL;
  • TIdSSLIOHandlerSocketOpenSSL.SSLOptions.Method=sslTLSv1_2;
  • TIdHTTP.Request.UserAgent已替换为现代 UA。

点击 Run,输入https://httpbin.org/get,应返回 JSON:

{ "args": {}, "headers": { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) ..." } }

✅ 成功标志:状态栏显示200 OK,且响应体含"headers"字段。
❌ 失败信号:弹出EIdHTTPProtocolException且消息为SSL connect error—— 回头检查 OpenSSL DLL 路径。

6.2 TCP Server 验证:Demos\Core\TcpServer

此 Demo 启动一个监听127.0.0.1:8080的服务器,用telnet 127.0.0.1 8080连接后,输入任意文本并回车,服务器应原样返回。关键验证点:

  • 修改TcpServerMain.pas中TForm1.IdTCPServer1Execute:
    procedure TForm1.IdTCPServer1Execute(AContext: TIdContext); var Line: string; begin Line := AContext.Connection.IOHandler.ReadLn(#10); // 改为 \n 分隔 AContext.Connection.IOHandler.WriteLn('Echo: ' + Line); end;
  • 编译运行后,在 CMD 执行:
    telnet 127.0.0.1 8080 Hello Indy!
    应立刻收到Echo: Hello Indy!。

✅ 成功标志:telnet窗口不闪退,回显正确;任务管理器中TcpServer.exeCPU 占用 < 1%(说明无死循环)。
❌ 失败信号:telnet连接后无响应 —— 检查Bindings.IP是否为127.0.0.1,是否被防火墙拦截。

6.3 UDP Broadcast 验证:Demos\Core\UdpBroadcast

此 Demo 验证局域网广播能力,对某跨平台系统中的设备发现协议至关重要。运行UdpBroadcast.dpr后:

  • 点击Send Broadcast,向255.255.255.255:30000发送PING;
  • 另一台机器运行同一 Demo,点击Start Listening,应收到PONG from 192.168.1.100。

若收不到,检查:

  • 两台机器是否在同一子网(ipconfig确认192.168.1.x);
  • Windows 防火墙是否放行 UDP 30000 端口(wf.msc→ 入站规则);
  • TIdUDPClient.BroadcastEnabled是否为True(Demo 中已设)。

6.4 压测技巧:用curl模拟 100 并发连接

GUI Demo 只能验证功能,不能验证稳定性。我习惯用curl做轻量压测:

# 启动 TcpServer Demo(监听 8080) # 在另一终端执行: for /L %i in (1,1,100) do @start "" curl -s "http://127.0.0.1:8080/?id=%i" > nul

观察TcpServer.exe的内存占用:

  • 100 并发下,内存增长应 < 30 MB;
  • 无Access Violation或EIdSocketError弹窗;
  • 所有curl进程在 2 秒内完成(time curl ...测试单次)。

从那以后我每次部署 Indy 10.2.3,都强制走一遍这三 Demo + 一次curl并发,哪怕只是更新一个补丁。因为TIdTCPClient.Connect的静默失败,永远比编译报错更难 debug——它不告诉你哪里错了,只让你在凌晨三点对着空白日志发呆。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询