寻求C++Builder下Indy的TCP示例及ISO8583中间人网关入门模板
C++Builder + Indy 10 TCP中间人网关模板(适配ISO8583分析场景)
核心实现逻辑
- 用
TIdTCPServer监听客户端连接,每收到一个客户端连接,动态创建TIdTCPClient实例连接真实服务器 - 实现客户端与服务器的数据流双向转发,同时捕获原始二进制数据用于后续ISO8583解析
- 处理连接断开的异常与资源释放,确保网关稳定运行
完整代码模板
步骤1:组件准备
在C++Builder窗体中添加以下组件:
TIdTCPServer(命名为IdTCPServer1)TMemo(命名为MemoLog,用于记录日志和数据,可选)
步骤2:代码实现
#include <vcl.h> #pragma hdrstop #include "MainForm.h" #include <IdTCPClient.hpp> #include <IdTCPConnection.hpp> #include <IdTCPServer.hpp> #include <IdGlobal.hpp> //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; // 关联客户端与服务器连接的结构体 struct TClientServerPair { TIdContext* ClientContext; TIdTCPClient* ServerClient; bool IsActive; }; // 存储所有活跃连接对 TList* ClientServerPairs = new TList(); //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { // 配置监听服务器 IdTCPServer1->DefaultPort = 10000; // 替换为你的监听端口 IdTCPServer1->OnConnect = &IdTCPServer1Connect; IdTCPServer1->OnDisconnect = &IdTCPServer1Disconnect; IdTCPServer1->OnExecute = &IdTCPServer1Execute; IdTCPServer1->Active = true; MemoLog->Lines->Add("中间人网关已启动,监听端口:10000"); } //--------------------------------------------------------------------------- void __fastcall TForm1::IdTCPServer1Connect(TIdContext *AContext) { MemoLog->Lines->Add("客户端连接:" + AContext->Binding->PeerIP + ":" + IntToStr(AContext->Binding->PeerPort)); // 创建并连接真实服务器 TIdTCPClient* ServerClient = new TIdTCPClient(this); ServerClient->Host = "127.0.0.1"; // 替换为真实服务器IP ServerClient->Port = 20000; // 替换为真实服务器端口 ServerClient->ConnectTimeout = 5000; try { ServerClient->Connect(); MemoLog->Lines->Add("已连接到真实服务器"); // 保存连接对并关联到客户端上下文 TClientServerPair* Pair = new TClientServerPair(); Pair->ClientContext = AContext; Pair->ServerClient = ServerClient; Pair->IsActive = true; ClientServerPairs->Add(Pair); AContext->Data = Pair; } catch (Exception& E) { MemoLog->Lines->Add("连接真实服务器失败:" + E.Message); delete ServerClient; AContext->Connection->Disconnect(); } } //--------------------------------------------------------------------------- void __fastcall TForm1::IdTCPServer1Disconnect(TIdContext *AContext) { MemoLog->Lines->Add("客户端断开:" + AContext->Binding->PeerIP + ":" + IntToStr(AContext->Binding->PeerPort)); // 清理对应服务器连接 TClientServerPair* Pair = static_cast<TClientServerPair*>(AContext->Data); if (Pair && Pair->IsActive) { Pair->IsActive = false; if (Pair->ServerClient->Connected()) { Pair->ServerClient->Disconnect(); } delete Pair->ServerClient; ClientServerPairs->Remove(Pair); delete Pair; } } //--------------------------------------------------------------------------- void __fastcall TForm1::IdTCPServer1Execute(TIdContext *AContext) { TClientServerPair* Pair = static_cast<TClientServerPair*>(AContext->Data); if (!Pair || !Pair->IsActive || !Pair->ServerClient->Connected()) { return; } TIdTCPConnection* ClientConn = AContext->Connection; TIdTCPConnection* ServerConn = Pair->ServerClient->Connection; // 读取客户端二进制数据并转发 if (ClientConn->IOHandler->InputBuffer->Size > 0) { TIdBytes ClientData; // 按可用数据全读,后续可根据ISO8583长度字段调整读取逻辑 ClientConn->IOHandler->ReadBytes(ClientData, ClientConn->IOHandler->InputBuffer->Size); // 记录十六进制格式数据,方便解析 AnsiString HexData = BytesToHex(ClientData); MemoLog->Lines->Add("收到客户端数据(Hex):" + HexData); ServerConn->IOHandler->Write(ClientData); } // 读取服务器响应并转发给客户端 if (ServerConn->IOHandler->InputBuffer->Size > 0) { TIdBytes ServerData; ServerConn->IOHandler->ReadBytes(ServerData, ServerConn->IOHandler->InputBuffer->Size); AnsiString HexData = BytesToHex(ServerData); MemoLog->Lines->Add("收到服务器响应(Hex):" + HexData); ClientConn->IOHandler->Write(ServerData); } // 检测连接状态,异常则断开 if (!ClientConn->Connected() || !ServerConn->Connected()) { AContext->Connection->Disconnect(); } } //--------------------------------------------------------------------------- __fastcall TForm1::~TForm1() { // 程序退出时清理所有连接 for (int i = 0; i < ClientServerPairs->Count; i++) { TClientServerPair* Pair = static_cast<TClientServerPair*>(ClientServerPairs->Items[i]); if (Pair->IsActive) { if (Pair->ServerClient->Connected()) { Pair->ServerClient->Disconnect(); } delete Pair->ServerClient; Pair->IsActive = false; } delete Pair; } delete ClientServerPairs; }
关键问题解决
1. 连接断开无提示
- 利用
TIdTCPServer的OnDisconnect事件捕获客户端断开,同时在OnExecute循环中定期检查客户端和服务器的连接状态 - 客户端断开时主动断开对应服务器连接并释放资源,避免内存泄漏
2. 获取实际二进制数据
- 必须使用
ReadBytes()读取原始二进制流,禁止使用ReadLn()等文本读取方法 - 通过
BytesToHex()将二进制转为十六进制字符串,便于查看和后续ISO8583解析 - 后续可根据ISO8583协议的长度字段(如前2字节表示报文长度),调整
ReadBytes()的参数实现精准读取
后续扩展建议
- 将数据捕获逻辑独立为模块,把
ClientData和ServerData传递给ISO8583解析组件 - 添加配置界面,支持动态修改监听端口、服务器IP/端口
- 增加日志持久化功能,将报文数据保存到文件或数据库
- 实现报文过滤、修改功能,满足中间人分析的定制需求
内容的提问来源于stack exchange,提问作者Beto
相关产品推荐
相关产品推荐

