为何需发送两次消息才能触发Indy的OnExecute事件?
ISO 8583中间人分析应用问题排查
项目背景
- 开发一款基于TCP/IP的ISO 8583协议中间人分析应用,核心目标是抓取原始二进制数据并转换为字符串进行协议解析
- 使用
TIdMappedPortTCP组件,测试工具为Hercules - 开发环境:
- Windows 11 Home
- Embarcadero® CBuilder 10.4 Version 27.0.40680.4203(包含Delphi和C Builder 10.4 Update 2)
- Indy 10.6.2.0
核心问题
必须发送两次消息才能触发OnExecute事件,怀疑与长度计算逻辑有关,但未定位到具体问题。此外关闭应用时会出现冻结现象,其余功能符合预期。
测试数据
在Hercules中使用的测试数据:
00 04 60 02
等价于C++代码中的:
"\x00\x04\x60\x02"
相关代码
初始OnExecute事件代码
void __fastcall TForm1::MITMProxyExecute(TIdContext *AContext) { static int index; TIdBytes ucBuffer; UnicodeString usTemp1; UnicodeString usTemp2; int calculated_length; // 获取十六进制格式的消息长度 calculated_length = ReadMessageLength(AContext); // 读取指定长度的数据 AContext->Connection->IOHandler->ReadBytes(ucBuffer, calculated_length); // 显示计算长度与实际读取的数据大小 usTemp2 = UnicodeString("calculated length = "); usTemp2 += IntToStr(calculated_length); usTemp2 += " ucBuffer.Length = "; usTemp2 += IntToStr(ucBuffer.Length); Display->Lines->Add(usTemp2); // 将二进制数据转为十六进制字符串用于可视化 usTemp1 = BytesToHexString(ucBuffer); // 添加索引区分不同消息条目 usTemp2 = IntToStr(index); usTemp2 += UnicodeString(": "); usTemp2 += usTemp1; Display->Lines->Add(usTemp2); index++; }
辅助函数代码(含字节转十六进制优化疑问)
// 将字节数组转换为十六进制字符串 UnicodeString BytesToHexString(const TBytes& bytes) { UnicodeString hexString; for (int i = 0; i < bytes.Length; i++) { hexString += IntToHex(bytes[i], 2); } return hexString; } // 读取消息前两个字节并解析为消息长度 int ReadMessageLength(TIdContext *AContext) { int calculated_length; // 使用ReadSmallInt读取前两个字节作为长度值 calculated_length = AContext->Connection->IOHandler->ReadSmallInt(); // 将二进制值转换为十六进制字符串 UnicodeString bcdLength = UnicodeString().sprintf(L"%04x", calculated_length); // 将十六进制字符串转换为整数 calculated_length = bcdLength.ToInt(); // 减去长度字段自身的2字节 calculated_length -= 2; return calculated_length; }
更新后的代码(处理UI线程同步,但问题仍存在)
UI同步类代码
class TAddTextToDisplay : public TIdSync { private: UnicodeString textToAdd; public: __fastcall TAddTextToDisplay(UnicodeString str) { textToAdd = str; } virtual void __fastcall DoSynchronize() { if (textToAdd != NULL) { Form1->Display->Lines->Add(textToAdd); } } void __fastcall setTextToAdd(UnicodeString str) { textToAdd = str; } };
更新后的OnExecute事件代码
void __fastcall TForm1::MITMProxyExecute(TIdContext *AContext) { static int index; TIdBytes ucBuffer; UnicodeString usTemp1; UnicodeString usTemp2; int calculated_length; int bytes_remaining; // 获取十六进制格式的消息长度 calculated_length = ReadMessageLength(AContext); if (!AContext->Connection->IOHandler->InputBufferIsEmpty()) { // 读取指定长度的数据 AContext->Connection->IOHandler->ReadBytes(ucBuffer, calculated_length); // 显示计算长度与实际读取的数据大小 usTemp2 = UnicodeString("calculated length = "); usTemp2 += IntToStr(calculated_length); usTemp2 += " ucBuffer.Length = "; usTemp2 += IntToStr(ucBuffer.Length); TAddTextToDisplay *AddTextToDisplay = new TAddTextToDisplay(usTemp2); AddTextToDisplay->Synchronize(); // 将二进制数据转为十六进制字符串用于可视化 usTemp1 = BytesToHexString(ucBuffer); // 添加索引区分不同消息条目 usTemp2 = IntToStr(index); usTemp2 += UnicodeString(": "); usTemp2 += usTemp1; AddTextToDisplay->setTextToAdd(usTemp2); AddTextToDisplay->Synchronize(); delete AddTextToDisplay; index++; } }
内容的提问来源于stack exchange,提问作者Beto
相关产品推荐
相关产品推荐

