tIdHttpServer - 在发送 POST 回复之前 EidConnClosed

发布于 2024-09-12 19:54:29 字数 2934 浏览 12 评论 0原文

我在 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) 行引发 EidConnClosedGraceously 。这是我处理传入 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 认为断开连接发生在

点击此处查看图片

I am having trouble implementing a HTTP server with indy 10 in delphi 2007.

I have set up a simple event handler for the CommandGet event.

When replying to data sent using the GET method I can parse the params and send XML data back with no problems. (see code below)

    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);

When I try to reply to the data that is sent using a POST the response is never sent by indy, instead a EidConnClosedGracefully is raised by TIdIOHandler.WriteDirect form the CheckForDisconnect(True, True) line. here is how i'm handling the incoming POST data

    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);

I have used wireshark to see what is happening and it looks like indy is sending an ACK back before the response is sent and causing the client to disconnect.

to test this I set-up Apache with PHP and wrote a PHP script to do the same job and everything works ok, The difference is the POST data is replied to with the response content not an ACK.

any suggestions on how to resolve this so I respond to the POST data as well as GET.


I'm stuck with this now, as you can see from this wireshark trace (click link for image) i have increased the timeout to 20 seconds. and its still not working. I'm going to do some more investigations. and see what I can find out. Its looking like Indy thinks the disconnect has occurred before it has

Click here for image

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

北凤男飞 2024-09-19 19:54:29

看起来 http 正在发送为

Transfer-Encoding: chunked

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

Looks like the http is being sent as

Transfer-Encoding: chunked

Therefore there is no content-length. but the version of Indy I am using doesn't support this mode.

风向决定发型 2024-09-19 19:54:29

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

ACKs are not sent by Indy itself, but by the underlying socket instead, and even then only in reply to packets received from the other party. EIdConnClosedGracefully means that the client is intentionally disconnecting the socket on its end before your server can sent its reply data. The fact that an ACK is present helps prove that (the socket is likely ACK'ing the client's FIN packet during disconnection).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文