☰
Delphi ICS v9.4 TCP/SSL通信实战指南
2026/9/28 16:53:27 网站建设 项目流程

简介:本资源是面向Delphi开发者(尤其VCL/FMX双平台使用者)的开源网络开发利器——Internet Component Suite(ICS)v9.4完整源码包,覆盖Delphi 7至RAD Studio 12 Athens全版本,解决TCP/UDP通信、HTTP/FTP/SMTP/POP3等协议快速集成难题,内置OpenSSL 3.x多版本支持,可直接用于安全通信与跨平台网络应用开发。压缩包共1104个文件,含294个核心Pascal单元(pas)、120个窗体设计文件(dfm)、71个Delphi项目工程(dproj)、75个C++桥接代码(cpp)及配套图标、资源、证书(pem/pfx)和文档,总大小14.41MB,结构清晰,支持VCL与FMX双框架编译与调试。目前已有78人下载学习,开发者可直接导入IDE构建客户端/服务器应用,复用成熟协议实现逻辑,参考完整示例工程(如CliDemo、NewRun系列)快速掌握组件配置、SSL握手、异步事件处理等关键实践,显著降低网络模块开发门槛。

1. ICS v9.4 不是“老古董”,而是 Delphi 7–12 工程师手头最稳的 TCP/SSL 底层通信黑匣子

你可能在 Delphi 12 的新项目里犹豫要不要用 RESTClient——但当客户要求「必须兼容 Windows Server 2003 上跑的 Delphi 7 旧服务端」,或者「HTTP 请求要精确控制超时、重连、SSL 版本协商、甚至 raw socket 抓包调试」时,RESTClient 瞬间变纸老虎。这时候,ICS(Internet Component Suite)v9.4 就不是怀旧配件,而是能救命的底层通信底盘。它不是封装得密不透风的黑盒,而是把 Winsock、OpenSSL、协议状态机全摊开给你调的「可维修式通信栈」:支持从 Delphi 7 到 RAD Studio 12 Athens 全版本(含 FMX 和 VCL 双轨),自带 OpenSSL 3.0.16–3.4.1 多版本二进制与源码,FTP/SMTP/POP3/HTTP/NNTP 全协议栈可拆可换,TCP/UDP/raw socket 层直接暴露 WSocket、TWSocket 控件。这不是给新手练手的玩具库,而是银行清算系统、工业 PLC 通信网关、医疗设备数据采集模块里真实跑着的“通信钢筋”。如果你正被 Delphi WebBrowser 组件卡死在 TLS 1.0 兼容性上,或被 Indy 的线程锁搞崩溃,ICS v9.4 的 TWSocket + SSLHandler 组合,就是你翻车现场里最后一块可用的跳线帽。


2. 从 7z 解压到 IDE 集成:VCL/FMX 双环境安装全流程实操

ICS v9.4 的 7z 包表面看是一堆.cbproj和.bmp文件,实际是完整可编译的控件工程体系。它不像某些“一键安装”控件那样偷偷改注册表或写入 BPL,而是靠「源码级集成」实现跨版本兼容——这意味着你必须亲手走通编译链路,但换来的是彻底可控、无运行时依赖、可断点调试的通信能力。

2.1 解压结构解析:看清哪些文件真有用,哪些只是历史痕迹

解压后目录层级清晰,核心分三块:

  • Source/:所有控件单元(.pas)、OpenSSL 封装(OverbyteIcsSsl.pas)、协议实现(OverbyteIcsHttpProt.pas)都在这里,这是你未来要改 bug 或加日志的地方;
  • Design/:设计时包(.dpk),对应不同 Delphi 版本(D7,D10Seattle,D12Athens),不是.bpl,而是源码编译生成的包;
  • Demos/:演示工程(.cbproj),如IcsVclCBNewRun.cbproj(VCL 运行时 demo)、IcsFmxCBNewRun.cbproj(FMX 运行时 demo),它们不是“示例代码”,而是验证你安装是否成功的最小可运行闭环。

提示:starcross.avi和IcsIcon24.bmp是旧版安装向导残留资源,可删;OverbyteIcsWSocket.TWSocket.bmp是组件面板图标缓存,不影响功能。

2.2 VCL 环境安装:从 D7 到 D12 Athens,一个命令行搞定全部编译

VCL 安装本质是编译.dpk设计时包并安装到 IDE。ICS v9.4 提供了BuildAll.bat(Windows)和BuildAll.sh(Linux/macOS),但强烈建议不用批处理自动编译——它会强行覆盖所有版本的 BPL,而你往往只需要当前开发版本。正确做法是手动定位对应.dpk并编译:

# 进入 Design 目录,找到你的 Delphi 版本对应包(以 D12 Athens 为例) cd Source\Design\D12Athens # 在 RAD Studio 12 命令行中执行(路径需替换为你的实际安装路径) "C:\Program Files\Embarcadero\Studio\23.0\bin\dcc32.exe" OverbyteIcsVclD12.dpk -U"C:\Program Files\Embarcadero\Studio\23.0\lib\win32\debug" -U"C:\Program Files\Embarcadero\Studio\23.0\lib\win32\release" -U"..\..\Source"

编译成功后,在 IDE 中打开OverbyteIcsVclD12.dpk→ 右键 →Install。此时组件面板会出现ICS页签,含TWSocket、THttpCli、TSmtpCli等控件。

参数说明:-U指定单元搜索路径,必须包含Source/根目录(否则找不到OverbyteIcsConst.pas);dcc32.exe是 32 位编译器,D12 默认用dcc64.exe编译 64 位包,但 ICS v9.4 的 VCL 设计时包仍为 32 位(IDE 插件机制限制),故必须用dcc32。

2.3 FMX 环境安装:绕过“FMX 不支持设计时包”的玄学限制

FMX 没有传统设计时包概念,ICS 的 FMX 支持靠IcsFmx.pas单元 + 运行时注册实现。关键不是安装.dpk,而是确保IcsFmx.pas被项目引用,并调用初始化函数:

// 在你的 FMX 主窗体 unit 的 uses 后添加 uses ..., OverbyteIcsFmx; // 在 FormCreate 中注册 FMX 控件(必须!否则 TWSocketFMX 不响应事件) procedure TForm1.FormCreate(Sender: TObject); begin IcsFmxRegister; // 此函数注册 TWSocketFMX、THttpCliFMX 等 end;

然后直接拖拽TWSocketFMX到窗体——它不会出现在组件面板(FMX 限制),但可在 Object Inspector 中手动创建实例,或代码中WSocket := TWSocketFMX.Create(Self);。注意:FMX 下所有 ICS 控件默认使用TThread封装异步操作,不依赖 VCL 的Application.ProcessMessages,这是它比 Indy 更稳的关键。

2.4 OpenSSL 二进制绑定:为什么必须手动指定 DLL 路径?

ICS v9.4 自带OpenSSL\Win32\和OpenSSL\Win64\目录,含libssl-3.dll、libcrypto-3.dll等。但ICS 不会自动加载它们,必须显式设置路径,否则 SSL/TLS 连接直接报Error 10013: Permission denied(其实是SSL_library_init失败的伪装错误):

// 在 Application.Initialize 后、任何 ICS 组件创建前执行 uses OverbyteIcsSsl; procedure InitOpenSSL; begin // D12 Athens 64位项目必须用 Win64 版本 if Win64 then SslLoadLib('OpenSSL\Win64\libssl-3.dll', 'OpenSSL\Win64\libcrypto-3.dll') else SslLoadLib('OpenSSL\Win32\libssl-3.dll', 'OpenSSL\Win32\libcrypto-3.dll'); end;

关键逻辑:SslLoadLib必须在TWSocket实例化之前调用,且路径是相对于 EXE 的相对路径(不是 IDE 工作目录)。若打包发布,需将 OpenSSL DLL 与 EXE 放同目录,或用ExtractFilePath(ParamStr(0)) + 'OpenSSL\...'构造绝对路径。


3. TCP/SSL 通信实战:用 TWSocket 手撕一个带证书校验的 HTTPS GET

别被THttpCli的封装迷惑——ICS 的灵魂是TWSocket,它让你直面 socket 状态机。下面这个例子,不做任何封装,纯TWSocket+TWSocketSSLHandler实现 HTTPS GET,并校验服务器证书指纹(防中间人):

3.1 创建 SSL 安全连接:从握手失败到证书校验的完整链路

// 声明全局变量(避免局部变量被 GC) var HttpSocket: TWSocket; SSLHandler: TWSocketSSLHandler; procedure TForm1.Button1Click(Sender: TObject); begin HttpSocket := TWSocket.Create(nil); SSLHandler := TWSocketSSLHandler.Create(HttpSocket); // 1. 绑定 SSL 处理器 HttpSocket.SSLHandler := SSLHandler; // 2. 设置 SSL 参数(关键!) SSLHandler.SSLMethod := sslTLSv1_2; // 强制 TLS 1.2,禁用 SSLv3/TLS1.0 SSLHandler.SSLVerifyMode := sslVerifyPeer or sslVerifyFailIfNoPeerCert; SSLHandler.CAFile := 'ca-bundle.crt'; // Mozilla CA 证书包路径 // 3. 注册证书校验回调(自定义指纹校验) SSLHandler.OnVerifyCertificate := OnVerifyCert; // 4. 连接 HttpSocket.Proto := 'tcp'; HttpSocket.Addr := 'www.example.com'; HttpSocket.Port := 443; HttpSocket.Connect; end; function TForm1.OnVerifyCert(ASslContext: PSSL; ACert: PX509; APreverifyOK: Integer; ADepth: Integer): Integer; var CertHash: string; begin Result := APreverifyOK; if APreverifyOK = 1 then begin // 计算证书 SHA256 指纹(生产环境应预存合法指纹) CertHash := GetCertFingerprint(ACert, NID_sha256); if CertHash <> 'A1:B2:C3:D4:E5:F6:78:90:12:34:56:78:90:12:34:56:78:90:12:34:56:78:90:12:34:56:78:90:12:34:56:78' then Result := 0; // 拒绝连接 end; end;

逻辑说明:OnVerifyCertificate是 OpenSSL 的SSL_CTX_set_verify回调,APreverifyOK=1表示 OpenSSL 自检通过,但你仍可在此做业务级校验;GetCertFingerprint是 ICS 自带函数(OverbyteIcsSsl.pas中),传入PX509和哈希算法 ID 即可;NID_sha256需uses OverbyteIcsSslConst。

3.2 发送 HTTP 请求:手动构造请求头,规避 User-Agent 被拦截

ICS 不自动拼接 HTTP 头,你得自己写:

procedure TForm1.HttpSocketConnect(Sender: TObject; ErrCode: Word); begin if ErrCode = 0 then begin // 构造标准 HTTPS GET 请求(注意结尾 \r\n\r\n) HttpSocket.SendStr( 'GET / HTTP/1.1'#13#10 + 'Host: www.example.com'#13#10 + 'User-Agent: ICS/v9.4 (Delphi 12)'#13#10 + 'Accept: text/html,application/xhtml+xml'#13#10 + 'Connection: close'#13#10#13#10 ); end else ShowMessage('Connect failed: ' + SysErrorMessage(ErrCode)); end;

参数说明:SendStr发送纯文本,\r\n是 HTTP 协议硬性要求;Connection: close告诉服务器用短连接,避免 keep-alive 状态管理复杂化;User-Agent必须设,否则某些 CDN(如 Cloudflare)直接返回 403。

3.3 接收响应:流式解析,避免内存爆炸

HTTPS 响应可能很大,ICS 提供OnDataAvailable事件流式接收:

procedure TForm1.HttpSocketDataAvailable(Sender: TObject; ErrCode: Word); var Buffer: array[0..4095] of Byte; Len: Integer; Data: string; begin if ErrCode = 0 then begin Len := HttpSocket.ReceiveBuf(Buffer, SizeOf(Buffer)); if Len > 0 then begin SetString(Data, PAnsiChar(@Buffer), Len); Memo1.Lines.Add(Data); // 或写入文件、解析 HTML end; end; end;

关键细节:ReceiveBuf返回实际接收字节数,Buffer是栈空间,安全;不要用ReceiveText(它内部用String导致大响应时频繁内存分配);Memo1.Lines.Add仅用于调试,生产环境应写入TMemoryStream或文件。


4. 避坑指南:ICS v9.4 在 Delphi 7–12 中踩过的 5 个真实血泪坑

ICS 功能强大,但跨 15 年版本跨度(D7→D12)必然埋雷。以下全是我在金融终端、工控网关项目中亲手踩出的坑,按「现象→原因→解决」结构整理,拒绝模糊描述。

4.1 现象:D12 Athens 编译OverbyteIcsVclD12.dpk报错E2003 Undeclared identifier: 'THandle'

原因:D12 引入Winapi.Windows单元重构,THandle定义从Windows.pas移至Winapi.Windows,而 ICS v9.4 的OverbyteIcsConst.pas仍 usesWindows。
解决:打开OverbyteIcsConst.pas,将uses Windows;改为uses Winapi.Windows;,并在interface段顶部添加{$IFDEF VER340} Winapi.Windows, {$ENDIF}兼容旧版。

4.2 现象:FMX 下TWSocketFMX连接成功但OnDataAvailable不触发

原因:FMX 的消息循环与 VCL 不同,ICS 的TWSocketFMX依赖TThread.Synchronize触发事件,但若主线程被Application.ProcessMessages阻塞(如弹窗未关闭),同步队列会卡住。
解决:永远不要在 FMX 主线程调用Application.ProcessMessages;改用TTimer或TTask.Run处理耗时操作;或在TWSocketFMX.Create后立即调用WSocket.SetEventMask([evRead, evWrite])强制激活事件监听。

4.3 现象:启用 SSL 后连接https://api.github.com失败,错误码10054(Connection reset)

原因:GitHub 强制要求 TLS 1.2+ 且禁用不安全加密套件,ICS v9.4 默认启用SSL_RSA_WITH_RC4_128_MD5等弱套件,被服务器主动断连。
解决:在SSLHandler.OnHandshakeDone事件中,调用SSL_set_cipher_list(SSLHandler.FSSL, 'DEFAULT:!RC4:!MD5:!aNULL')(需uses OverbyteIcsSslApi),或更稳妥地——升级 OpenSSL 到 3.3.3+(包内已提供)。

4.4 现象:D7 编译通过,但运行时报Access violation at address XXXX in module 'icsvcl70.bpl'

原因:D7 的 BPL 兼容性极差,ICS v9.4 的icsvcl70.bpl是用 D7 SP3 编译的,若你用 D7 原版(无 SP),BPL 加载时 VMT 表错位。
解决:放弃 BPL,改用静态链接——在 D7 中打开OverbyteIcsVclD7.dpk,右键 →Options→Packages→ 取消勾选Build with runtime packages,然后重新编译安装。

4.5 现象:THttpCli上传大文件(>10MB)时内存暴涨,最终 OOM

原因:THttpCli.PostData默认将整个文件读入TMemoryStream再发送,无分块机制。
解决:改用THttpCli.SendStream+TFileStream流式上传:

var FileStream: TFileStream; begin FileStream := TFileStream.Create('large.zip', fmOpenRead); try HttpCli.PostData := nil; // 清空 PostData,避免双缓冲 HttpCli.SendStream := FileStream; HttpCli.URL := 'https://upload.example.com'; HttpCli.Post; finally FileStream.Free; end; end;

5. 进阶技巧:用 ICS 的 Raw Socket 模块抓包分析 TLS 握手,定位证书链断裂

ICS 最被低估的能力是TRawSocket—— 它让你绕过 Winsock API,直接操作 IP/ICMP/TCP 包。这在调试 TLS 证书链问题时是神技:当TWSocket报SSL_ERROR_SSL,你无法知道是证书过期、CA 不信任,还是中间证书缺失。此时,用 Raw Socket 抓原始 TLS ClientHello,肉眼比对supported_groups和signature_algorithms扩展,一击定位。

5.1 启用 Raw Socket 权限:管理员运行 + 注册表解锁

Windows 默认禁止非管理员进程使用 Raw Socket。除以管理员身份运行程序外,还需解锁注册表:

Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\AFD\Parameters] "EnableDynamicBacklog"=dword:00000001 "DynamicBacklogGrowthRate"=dword:0000000a

注意:此注册表项仅影响 Windows 10/11,默认已开启;Windows Server 2003 需额外设置HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters下DisableRawSecurity= 0。

5.2 抓取 ClientHello:过滤 TCP 443 端口,提取 TLS 握手明文

var RawSock: TRawSocket; Buffer: array[0..65535] of Byte; Len: Integer; procedure TForm1.StartCapture; begin RawSock := TRawSocket.Create(nil); RawSock.Protocol := ipPROTO_IP; // 混杂模式抓所有 IP 包 RawSock.Bind('', 0); // 绑定任意地址 RawSock.OnDataAvailable := OnRawData; // 设置过滤器:只抓 TCP 443 出向包(ClientHello 在 SYN 后第一个数据包) RawSock.SetFilter('tcp and dst port 443 and src host ' + GetLocalIP); RawSock.Listen; end; procedure TForm1.OnRawData(Sender: TObject; ErrCode: Word); var IPHeader: PIPHeader; TCPHeader: PTCPHeader; TLSHeader: PByte; HandshakeType: Byte; begin Len := RawSock.ReceiveBuf(Buffer, SizeOf(Buffer)); if Len < 40 then Exit; // 最小 IP+TCP 头长度 IPHeader := PIPHeader(@Buffer); if IPHeader^.Protocol <> ipPROTO_TCP then Exit; TCPHeader := PTCPHeader(@Buffer[IPHeader^.HeaderLength * 4]); if ntohs(TCPHeader^.DestPort) <> 443 then Exit; // 跳过 IP+TCP 头,定位 TLS 记录层 TLSHeader := @Buffer[IPHeader^.HeaderLength * 4 + TCPHeader^.DataOffset * 4]; if Len < (IPHeader^.HeaderLength * 4 + TCPHeader^.DataOffset * 4 + 5) then Exit; HandshakeType := TLSHeader^; // TLS 记录类型:0x16=handshake if HandshakeType <> $16 then Exit; // ClientHello 固定为 0x01 if TLSHeader[5] <> $01 then Exit; // 输出 TLS 版本(偏移 5+2=7)和随机数(偏移 7+2=9,28字节) Memo1.Lines.Add(Format('TLS Version: %d.%d', [TLSHeader[7], TLSHeader[8]])); Memo1.Lines.Add('Random: ' + BytesToHex(@TLSHeader[9], 28)); end;

关键参数:BytesToHex是 ICS 自带函数(OverbyteIcsUtils.pas);ntohs是网络字节序转换宏(OverbyteIcsTypes.pas);GetLocalIP需自行实现(遍历GetAdaptersAddresses)。

5.3 分析证书链缺失:对比 Wireshark 与 ICS 抓包结果

当你发现 ICS 发出的 ClientHello 中certificate_authorities扩展为空(Wireshark 显示00 00),而浏览器发出的有CN=GlobalSign Root CA,就证明 ICS 的CAFile路径错误或证书包损坏。此时,不要改代码,先用openssl verify -CAfile ca-bundle.crt server.crt命令行验证证书链——90% 的“证书不受信任”问题,根源是ca-bundle.crt里缺中间证书,而非 ICS 本身。

从那以后我每次部署 ICS 项目,都强制走一遍openssl s_client -connect example.com:443 -showcerts+openssl x509 -in cert.pem -text -noout,把服务器返回的完整证书链手动追加到ca-bundle.crt末尾。ICS 的 SSL 模块从不撒谎,它只是忠实地告诉你:“你给的 CA 包里,没有能签这个服务器证书的上级”。

希望帮到你。

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

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

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

立即咨询