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

如何通过Indy TIdHTTP获取连续HTTP实时交易数据流并在下载中读取

你之前使用返回字符串的TIdHTTP.Post重载无法实时获取数据,是因为Indy默认会等待整个HTTP响应传输完成后才会把完整内容拼接成字符串返回,而你的目标接口返回的是无限持续的推送流,永远不会结束传输,自然拿不到数据。

你不需要额外使用IdIOHandlerStream,现有的IdSSLIOHandlerSocketOpenSSL已经可以满足SSL传输需求,只需要改用带输出流的Post重载,配合TIdHTTP的OnWork事件实时处理收到的数据包即可,具体实现步骤如下:

1. 预先准备

首先在窗体类中声明一个缓冲变量,用来存储收到的不完整行数据,避免拆分JSON时出现断行:

private
  FRecvBuffer: string; // 存储未处理的不完整行数据

2. 配置组件属性

  • 把TIdHTTP组件的IOHandler属性绑定到IdSSLIOHandlerSocketOpenSSL,正常配置SSL参数即可,不需要额外调整IOHandler相关配置
  • 给TIdHTTP组件绑定OnWork事件,用来处理实时到达的数据包

3. 调整请求代码

不要使用返回字符串的Post重载,改用带输出流参数的重载:

var
  Lrequest: TStringList;
  LResponseStream: TMemoryStream;
begin
  Lrequest := TStringList.Create;
  LResponseStream := TMemoryStream.Create;
  try
    Lrequest.Values['__RequestVerificationToken'] := RequestVerificationToken;
    Lrequest.Values['acct'] := 'demo';
    Lrequest.Values['pwd'] := 'demo';

    FRecvBuffer := ''; // 每次发起请求前清空缓冲
    try
      // 带输出流的Post重载会持续把收到的响应数据写入LResponseStream
      Onhttp.Post('https://trading/data', Lrequest, LResponseStream);
    except
      on E: Exception do
        Memo1.Lines.Add(TimeToStr(Time) + ': ' + E.ClassName + ' 错误,信息:' + E.Message);
    end;
  finally
    LResponseStream.Free;
    Lrequest.Free;
  end;
end;

4. 实现OnWork事件逻辑

每次收到新的数据包时,从流中读取新增内容,按行拆分出完整的JSON对象进行处理:

procedure TForm1.OnhttpWork(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Int64);
var
  LNewData: string;
  LLine: string;
  LLineEndPos: Integer;
  LStreamPos: Int64;
begin
  // 只处理接收数据的事件,跳过发送数据的事件
  if AWorkMode <> wmRead then Exit;

  // 先记录流的当前位置,读完后复位,不影响Indy后续写入数据
  LStreamPos := Onhttp.Response.ContentStream.Position;
  try
    Onhttp.Response.ContentStream.Position := LStreamPos - (AWorkCount - Length(FRecvBuffer));
    // 读取本次新增的所有数据
    SetLength(LNewData, AWorkCount - Length(FRecvBuffer));
    Onhttp.Response.ContentStream.ReadBuffer(PChar(LNewData)^, Length(LNewData));
  finally
    Onhttp.Response.ContentStream.Position := LStreamPos;
  end;

  // 把新数据加入缓冲
  FRecvBuffer := FRecvBuffer + LNewData;

  // 逐行拆分完整的JSON
  while Pos(#10, FRecvBuffer) > 0 do
  begin
    LLineEndPos := Pos(#10, FRecvBuffer);
    LLine := Trim(Copy(FRecvBuffer, 1, LLineEndPos - 1));
    Delete(FRecvBuffer, 1, LLineEndPos);

    // 过滤空行,处理完整的JSON行
    if LLine <> '' then
    begin
      Memo1.Lines.Add(TimeToStr(Time) + ': 收到数据:' + LLine);
      // 此处添加你自己的JSON解析逻辑即可
    end;
  end;
end;

注意事项

  • 由于该请求是无限持续的流,Post方法会一直阻塞,所以不要把请求逻辑放在主线程执行,要放到独立的工作线程中运行,否则会导致界面卡死。
  • 需要停止接收数据时,直接调用Onhttp.Disconnect即可,会触发断开异常,正常捕获后处理退出逻辑即可。

内容的提问来源于stack exchange,提问作者Int20h

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 06:24:07