You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何需发送两次消息才能触发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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 15:35:25