1

Delphi 2007 で indy 10 を使用して HTTP サーバーを実装する際に問題が発生しています。

CommandGet イベントの単純なイベント ハンドラーをセットアップしました。

GET メソッドを使用して送信されたデータに返信する場合、params を解析して問題なく 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 によって送信されることはありません。代わりに、CheckForDisconnect(True, True) 行から TIdIOHandler.WriteDirect によって 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秒に増やしました。まだ機能していません。もう少し調査してみます。そして、私が見つけることができるものを見てください。インディは、切断が発生する前に切断が発生したと考えているようです

画像はこちら

4

2 に答える 2

2

httpが次のように送信されているようです

Transfer-Encoding: chunked

したがって、コンテンツの長さはありません。しかし、私が使用している Indy のバージョンはこのモードをサポートしていません。

于 2010-08-09T12:56:03.360 に答える
0

ACK は Indy 自体から送信されるのではなく、基礎となるソケットから送信されます。その場合でも、相手から受信したパケットに応答する場合にのみ送信されます。EIdConnClosedGracefully は、サーバーが応答データを送信する前に、クライアントが意図的にソケットを切断していることを意味します。ACK が存在するという事実は、それを証明するのに役立ちます (ソケットは、切断中にクライアントの FIN パケットに ACK を送信している可能性があります)。

于 2010-08-07T20:55:58.880 に答える