同一线程上的同一IdHTTP上有多个请求

时间:2019-04-11 01:53:18

标签: multithreading delphi idhttp

我有一个应用程序,它一天会发出数千个HTTP请求。 为了获得最佳性能,我决定只创建一次IdHTTP对象,并对所有请求使用相同的对象。 这是问题开始的地方。在为每个请求创建一个IdHTTP时,一切正常。 该代码非常基本:

constructor HTTPThread.Create;
begin
  inherited Create(false);
  httpObject:= TIdHTTP.Create(Nil);
  sslObject:= TIdSSLIOHandlerSocketOpenSSL.Create(Nil);
  sslObject.SSLOptions.Method:= sslvTLSv1_2;
  httpObject.IOHandler:= sslObject;
  httpObject.Request.Accept:= frmHTTPRequests.Edit1.Text;
  httpObject.Request.UserAgent:= frmHTTPRequests.Edit3.Text;
  httpObject.ReadTimeout:= 15000;
  httpObject.HandleRedirects:= true;
  FreeOnTerminate:= true;
  OnTerminate:= TerminateProc;
end;


procedure HTTPThread.DoRequests;
var
    htmlSource: string;
begin
    try
      htmlSource:= httpObject.Get(Link);
      //a bunch of other stuff with HTML source
    except
      on E : Exception do
      Synchronize(procedure
      begin
        errorList.Add(E.Message);
        errorList.SaveToFile('Error.txt');
      end);
    end;
end;

除了保存Error.txt文件以观察发生了什么以外,我创建了此文件... 有时,对于前1k个请求,代码运行良好,有时对于前2k个请求,代码会有所不同。突然,它开始在TXT文件上写入相同的错误:

  

连接被同级重置。 domain.com-套接字错误#10054

我试图断开httpObject的连接,尝试了httpObject.Request.Clear,似乎没有任何作用。 有没有机会做这项工作?

1 个答案:

答案 0 :(得分:1)

由于某些原因,当服务器用Connection reset by peer响应时,Indy不会关闭套接字,因此您需要手动进行操作。

    procedure HTTPThread.DoRequests;
    const
      MAX_TRIES_COUNT = 5;
    var
      htmlSource: string;
      TriesCount: Integer;
    begin
      TriesCount := 0;
      repeat
        try
          htmlSource:= httpObject.Get(Link);
          //a bunch of other stuff with HTML source
        except
          on E : Exception do
          begin
            if E.Message.Contains('by peer') then
            begin
              httpObject.Disconnect;
              // Try to solve network connection issues
              Continue;
            end;
            else
            begin
              // Some other error handlers
            end;
          end;
          inc(TriesCount);
        end;
      until (httpObject.ResponseCode = 200) or (TriesCount > MAX_TRIES_COUNT);
    end;

P.S。我不建议您使用Synchronize()进行线程同步。尝试改用TCriticalSectionTMonitor