tIdHttpServer - 在发送 POST 回复之前 EidConnClosed
我在 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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
看起来 http 正在发送为
因此没有内容长度。但我使用的Indy版本不支持这种模式。
Looks like the http is being sent as
Therefore there is no content-length. but the version of Indy I am using doesn't support this mode.
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).