【问题标题】:IdHTTP Post returns connection reset by peer for Streams over 32KB对于超过 32KB 的流,IdHTTP Post 返回由对等方重置的连接
【发布时间】:2020-05-20 14:25:34
【问题描述】:

我在使用 HTTPS 发布到 Web 服务器时遇到问题。我不确定是我的问题还是服务器的问题。因此,如果我尝试发布大于 32KB 的 Stream,Delphi 会因 Socket Error 10054 - Connection reset by peer 而崩溃。 我将 Delphi XE5 与 Indy 的内部版本和最新的开放式 ssl dll 一起使用。 我还在 XE 上尝试了最新的 Indy 和 ssl dll。

这是我的部分代码

function TForm1.SendItemsList(aDataList: TStringList): Boolean;
var
  aHTTP: TIdHTTP;
  aRes: String;

  aURL: String;
  aErrMsg: String;

  aStrm: TMemoryStream;
  aResStrm: TMemoryStream;
  aXML: TNativeXML;
  aTmpNode: TXmlNode;
  aErrNode: TXmlNode;
  aList: TList;
  i: Integer;

begin
  Result := False;

  aStrm := TMemoryStream.Create;
  aResStrm := TMemoryStream.Create;
  aXML := TNativeXML.Create(nil);
  aHTTP := CreateHTTP('application/x-www-form-urlencoded');
  try
    aDataList.SaveToStream(aStrm);
    aStrm.Position := 0;
    aURL := Format(cIRPURL, ['1']);
    try
      aHTTP.Post(aURL, aStrm, aResStrm);
      aResStrm.Position := 0;

      aXML.LoadFromStream(aResStrm);

      aTmpNode := aXML.Root.FindNode('ResponseCode');
      if aTmpNode <> nil then
      begin
        if aTmpNode.Value <> '0' then
        begin
          aErrNode := aXML.Root.FindNode('ResponseText');
          aErrMsg := '';
          if aErrNode <> nil then
            aErrMsg := aErrNode.Value;
          aList := TList.Create;
          try
            aXML.Root.FindNodes('Detail', aList);
            for i := 0 to aList.Count-1 do
            begin
              aErrMsg := aErrMsg+#13#10+TXmlNode(aList[i]).Value;
            end;
          finally
            aList.Free;
          end;
        end;
      end;
    except
      on E:Exception do
      begin
        if E is EIdHTTPProtocolException then
          aErrMsg := E.Message + #13#10 + (E as EIdHTTPProtocolException).ErrorMessage
        else
          aErrMsg := E.Message;

        Exit;
      end;
    end;
  finally
    aXML.Free;
    aStrm.Free;
    aHTTP.Free;
    aResStrm.Free;
  end;

  Result := True;
end;

CreateHTTP 的样子

function TForm1.CreateHTTP(aContentType: String): TIdHTTP;
begin
  Result := TIdHTTP.Create(nil);
  Result.ConnectTimeout:=60000;
  Result.ReadTimeout:=90000;
  Result.ProtocolVersion:=pv1_1;
  Result.HTTPOptions := [hoForceEncodeParams];
  Result.HandleRedirects:=True;
  Result.IOHandler := SSLHandler;
  SSLHandler.ReadTimeout := 30000;
  Result.Request.Accept:='*/*';
  Result.Request.AcceptLanguage:='en-US';
  Result.Request.ContentType:=aContentType;
  Result.Request.CharSet:='utf-8';
  Result.Request.UserAgent := 'Mozilla/5.0';
end;

所有这些超时的存在只是因为我在测试为什么会出现该错误。然后我意识到问题在于要发送的流大于32KB。 我真的不能说代码有问题,因为以同样的方式,我将数据发送到亚马逊和沃尔玛等其他几个服务,例如我有时发送兆字节,但我没有收到任何错误。

服务器是IIS但我不知道什么版本,支持似乎不相信我一切正常。

我注意到 SSL 处理程序有一些默认缓冲区大小 - SendBufferSize 和 RecvBufferSize,默认为 32KB。好吧,我尝试将其设置为 1MB,但仍然出现相同的错误。 如果我发送小于 32KB 的内容,那么一切正常。执行 POST 后立即返回错误 - 没有延迟,只是立即错误。否则发送小流会导致在处理之前延迟一两秒,然后调试器转到下一行。我开始相信这是 IIS 的设置,确实有这样的设置,但那里的人说他们这边一切正常,他们的请求限制为 4MB。

服务提供商是IRPCommerce,但遗憾的是我无法提供测试链接,因为那里正在进行 IP 过滤。

我花了几天时间与他们讨论这个问题,在网上搜索问题、任何限制等。 那么我在这里遗漏了什么,印地的任何限制可能导致这个问题,我怀疑但只是为了确定我在问吗?我还能做些什么来更清楚地说明问题出在哪里?

编辑: 以下是 aDataList 的摘录:

Stock_ExternalStockID|Brands_Active|Brands_Brand|Models_Active|Models_Model|Models_Description|Models_AdditionalInformation1|Models_AdditionalInformation2|Stock_DisplayOrder|Stock_Option|Stock_Price|Stock_RRP|Stock_SupplierCost|Categories_Active|Categories_Name|Stock_PostageWeight|Stock_PartCode|Stock_ISBNNumber|Stock_UPCAPartCode|Stock_EAN13PartCode|Models_ImageURLs|OptionSelector|OptionSelectorAttributes|OptionSelectorCount|Stock_OutOfStockStatus
17664-00001|TRUE|Polypads|TRUE|Polypads Plus One Outsider Pet Bed|<ul><li>The perfect pet bed for any animal around the house or for covering car seats or boots for travelling. </li><li>Convenient to use.  </li><li>6cm Plus One thickness.  </li><li>Fully machine washable and quick drying. </li><li>As there is such an extensive range of colours available for the Polypad collection many colour combinations will have to be ordered in specifically; this service could take up to two weeks. </li><li>If you do not have any specific colours in mind please select, Colour Not Important, from the drop down menu.</li></ul>| | |10|Royal Blue-Navy|43.95|48.99|21.69|TRUE|Dog Beds|1000|160||||https://saddlery.biz/media/catalog/product/o/u/outp1.jpg|1|21,44|2|10
17664-00002|TRUE|Polypads|TRUE|Polypads Plus One Outsider Pet Bed|<ul><li>The perfect pet bed for any animal around the house or for covering car seats or boots for travelling. </li><li>Convenient to use.  </li><li>6cm Plus One thickness.  </li><li>Fully machine washable and quick drying. </li><li>As there is such an extensive range of colours available for the Polypad collection many colour combinations will have to be ordered in specifically; this service could take up to two weeks. </li><li>If you do not have any specific colours in mind please select, Colour Not Important, from the drop down menu.</li></ul>| | |20|Soft Blue-Royal Blue|43.95|48.99|21.69|TRUE|Dog Beds|1000|160||||https://saddlery.biz/media/catalog/product/o/u/outp1.jpg|1|21,44|2|10
17664-00003|TRUE|Polypads|TRUE|Polypads Plus One Outsider Pet Bed|<ul><li>The perfect pet bed for any animal around the house or for covering car seats or boots for travelling. </li><li>Convenient to use.  </li><li>6cm Plus One thickness.  </li><li>Fully machine washable and quick drying. </li><li>As there is such an extensive range of colours available for the Polypad collection many colour combinations will have to be ordered in specifically; this service could take up to two weeks. </li><li>If you do not have any specific colours in mind please select, Colour Not Important, from the drop down menu.</li></ul>| | |30|Black-Purple|43.95|48.99|21.69|TRUE|Dog Beds|1000|160||||https://saddlery.biz/media/catalog/product/o/u/outp1.jpg|1|21,44|2|10

这里有 165 行。如果我发送大约 40 个它们,它们就会发送,因为 40 个大约只有 32KB。我已确认数据不是问题,因为我已尝试将每一行逐一发送。

我尝试了 multipart/form-data,但没有成功。实际上,无论我问了多少次,他们都没有告诉我该使用什么,所以我使用了与沃尔玛相同的东西。

我认为服务器是 IIS 8.5。

【问题讨论】:

  • 要找出问题是客户端还是服务器端,您可以尝试另一个客户端来测试查询。例如,您可以在命令行上使用 curl(例如,请参阅 here)。
  • 实际上我为此使用了 Postman,但我收到 HTTP Method of GET is disallowed on this page. 而且我不确定我这样做是否正确,我都尝试了 Raw和选择文件的二进制文件
  • 你必须使用POST方法。
  • 我当然是使用POST方式,这不是我第一次使用Postman,但从来没有发送文件。但我不明白为什么它会返回该消息。
  • @GeorgiNikolov 您没有显示aDataList 的内容,但某些网络服务器确实对发布的数据大小有最大限制。你正在发布一个application/x-www-webform-urlencoded 请求,你确定服务器真的在期待吗?这种网络表单通常不会这么大。通过网络表单发布文件通常使用multipart/form-data,以便他们可以发布未编码的二进制数据。

标签: delphi https indy


【解决方案1】:

似乎“解决方案”是将Content-type更改为text/xml。其他提到的内容类型都不适用于大于 32KB 的流。同时,我得到了网站开发人员的确认,即在服务器端根本不考虑内容类型。 所以我真的很困惑这里发生了什么以及为什么只有'text/xml'可以正常工作。

【讨论】:

  • Indy 不在乎您将Content-Type 标头设置为什么,它只会按原样发送到服务器,因此由于Content-Type 值不同而导致的任何行为差异都必须在服务器端。
猜你喜欢
  • 2021-10-08
  • 1970-01-01
  • 1970-01-01
  • 2018-05-22
  • 2015-03-08
  • 2011-12-30
  • 1970-01-01
  • 2018-08-06
  • 2021-09-22
相关资源
最近更新 更多