1

我在 delphi 2007 中使用 indy 10 实现 HTTP 服务器时遇到问题。

我为 CommandGet 事件设置了一个简单的事件处理程序。

在回复使用 GET 方法发送的数据时,我可以解析参数并将 XML 数据发送回来,没有任何问题。(见下面的代码)

    Download := ARequestInfo.Params.Values['dld'];
    Config := ARequestInfo.Params.Values['config'];
    Flash := ARequestInfo.Params.Values['flash'];
    Employees := ARequestInfo.Params.Values['employees'];
    Schedule := ARequestInfo.Params.Values['schedules'];
    AppTables := ARequestInfo.Params.Values['apptables'];

    Heartbeat :=  NewHeartbeat;

    Heartbeat.Version.Dld := Download;
    Heartbeat.Version.Config := Config;
    Heartbeat.Version.Flash := Flash;
    Heartbeat.Version.Employee := Employees;
    Heartbeat.Version.Schedule := Schedule;
    Heartbeat.Version.AppTables := AppTables;

    AResponseInfo.ContentType := 'application/xml';
    AResponseInfo.ResponseNo := 200;
    AResponseInfo.ContentText := '<?xml version="1.0" encoding="utf-8"?>' +
      #13+#10 + FormatXMLData(Heartbeat.XML);

当我尝试回复使用 POST 发送的数据时,indy 永远不会发送响应,而是由 TIdIOHandler.WriteDirect 从 CheckForDisconnect(True, True) 行引发 EidConnClosedGracefully。这是我如何处理传入的 POST 数据

    XMLDocument1.xml.Clear;
    XMLDocument1.Active := True;
    XMLDocument1.XML.text := ARequestInfo.FormParams;

    SynMemo1.Lines.Add(ARequestInfo.FormParams);
    SynMemo1.Lines.Add(#13+#10);

    if XMLDocument1.XML.Count > 0 then
    begin
      XMLDocument1.XML.Delete(0);
      XMLDocument1.XML.Delete(0);

      for i := pred(xmldocument1.xml.count) downto 0 do
      begin
        stmp := XMLDocument1.XML.Strings[i];

        if Length(stmp) > 0 then
        begin
          if Copy(stmp,1,1) = '<' then
            break
          else
            XMLDocument1.XML.Delete(i);
        end
        else
          XMLDocument1.XML.Delete(i);

      end;

      XMLDocument1.XML.Text := StringReplace(XMLDocument1.XML.Text,
        '<Punches ', '<Punches xmlns="http://ats/punch" ', [rfReplaceAll]);



    end;

    Punch := GetPunches(XMLDocument1);

    PunchReply := NewOperationStatus;
    PunchReply.Uid := Punch.Uid;
    PunchReply.NodeValue := 'OK';

    stmp := '<?xml version="1.0" encoding="utf-8"?>' +
      #13+#10 + FormatXMLData(PunchReply.XML);
    SynMemo1.Lines.Add(stmp);
    SynMemo1.Lines.Add(#13+#10);

    AResponseInfo.ContentType := 'text/html';
    AResponseInfo.ContentStream := TStringStream.Create(stmp);

我已经使用wireshark查看发生了什么,看起来indy在发送响应之前发送了一个ACK并导致客户端断开连接。

为了测试这一点,我用 PHP 设置了 Apache 并编写了一个 PHP 脚本来做同样的工作,一切正常,不同之处在于 POST 数据是用响应内容而不是 ACK 来回复的。

关于如何解决这个问题的任何建议,所以我回复了 POST 数据和 GET。


我现在坚持这一点,正如您从这个 Wireshark 跟踪中看到的那样(单击图片链接),我已将超时时间增加到 20 秒。它仍然无法正常工作。我会做更多的调查。看看我能找到什么。看起来 Indy 认为在断开连接之前就已经发生了

点击这里查看图片

4

2 回答 2

2

看起来 http 被发送为

Transfer-Encoding: chunked

因此没有内容长度。但我使用的 Indy 版本不支持这种模式。

于 2010-08-09T12:56:03.360 回答
0

ACK 不是由 Indy 本身发送的,而是由底层套接字发送的,即使这样也只是为了回复从另一方收到的数据包。EIdConnClosedGracefully 意味着客户端在您的服务器可以发送其回复数据之前故意断开其端的套接字。存在 ACK 的事实有助于证明这一点(套接字可能在断开连接期间 ACK'ing 客户端的 FIN 数据包)。

于 2010-08-07T20:55:58.880 回答